1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_storage.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string>
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/bind_helpers.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/message_loop/message_loop.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/sequenced_task_runner.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/task_runner_util.h"
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/service_worker/service_worker_context_core.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_disk_cache.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/service_worker/service_worker_histograms.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_info.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h"
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "content/browser/service_worker/service_worker_utils.h"
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/service_worker/service_worker_version.h"
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/common/service_worker/service_worker_types.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/base/net_errors.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "webkit/browser/quota/quota_manager_proxy.h"
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid RunSoon(const tracked_objects::Location& from_here,
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu             const base::Closure& closure) {
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::MessageLoop::current()->PostTask(from_here, closure);
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid CompleteFindNow(
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const scoped_refptr<ServiceWorkerRegistration>& registration,
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ServiceWorkerStatusCode status,
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const ServiceWorkerStorage::FindRegistrationCallback& callback) {
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  callback.Run(status, registration);
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid CompleteFindSoon(
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const tracked_objects::Location& from_here,
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const scoped_refptr<ServiceWorkerRegistration>& registration,
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ServiceWorkerStatusCode status,
450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const ServiceWorkerStorage::FindRegistrationCallback& callback) {
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RunSoon(from_here, base::Bind(callback, status, registration));
470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const base::FilePath::CharType kServiceWorkerDirectory[] =
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    FILE_PATH_LITERAL("Service Worker");
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const base::FilePath::CharType kDatabaseName[] =
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    FILE_PATH_LITERAL("Database");
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const base::FilePath::CharType kDiskCacheName[] =
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FILE_PATH_LITERAL("Cache");
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const int kMaxDiskCacheSize = 250 * 1024 * 1024;
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void EmptyCompletionCallback(int) {}
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ServiceWorkerStatusCode DatabaseStatusToStatusCode(
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (status) {
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ServiceWorkerDatabase::STATUS_OK:
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return SERVICE_WORKER_OK;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND:
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return SERVICE_WORKER_ERROR_NOT_FOUND;
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case ServiceWorkerDatabase::STATUS_ERROR_MAX:
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      NOTREACHED();
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return SERVICE_WORKER_ERROR_FAILED;
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerStorage::InitialData::InitialData()
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : next_registration_id(kInvalidServiceWorkerRegistrationId),
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      next_version_id(kInvalidServiceWorkerVersionId),
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      next_resource_id(kInvalidServiceWorkerResourceId) {
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerStorage::InitialData::~InitialData() {
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ServiceWorkerStorage::ServiceWorkerStorage(
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::FilePath& path,
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::WeakPtr<ServiceWorkerContextCore> context,
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::SequencedTaskRunner* database_task_runner,
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoopProxy* disk_cache_thread,
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    quota::QuotaManagerProxy* quota_manager_proxy)
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : next_registration_id_(kInvalidServiceWorkerRegistrationId),
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      next_version_id_(kInvalidServiceWorkerVersionId),
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      next_resource_id_(kInvalidServiceWorkerResourceId),
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_(UNINITIALIZED),
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      context_(context),
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      database_task_runner_(database_task_runner),
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      disk_cache_thread_(disk_cache_thread),
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      quota_manager_proxy_(quota_manager_proxy),
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      is_purge_pending_(false),
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_factory_(this) {
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!path.empty())
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    path_ = path.Append(kServiceWorkerDirectory);
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_.reset(new ServiceWorkerDatabase(GetDatabasePath()));
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ServiceWorkerStorage::~ServiceWorkerStorage() {
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  database_task_runner_->DeleteSoon(FROM_HERE, database_.release());
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::FindRegistrationForDocument(
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& document_url,
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const FindRegistrationCallback& callback) {
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!document_url.has_ref());
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!LazyInitialize(base::Bind(
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &ServiceWorkerStorage::FindRegistrationForDocument,
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          weak_factory_.GetWeakPtr(), document_url, callback))) {
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (state_ != INITIALIZING || !context_) {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      SERVICE_WORKER_ERROR_FAILED, callback);
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // See if there are any stored registrations for the origin.
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!ContainsKey(registered_origins_, document_url.GetOrigin())) {
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Look for something currently being installed.
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<ServiceWorkerRegistration> installing_registration =
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FindInstallingRegistrationForDocument(document_url);
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CompleteFindNow(
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration,
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration ?
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        callback);
1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_task_runner_->PostTask(
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &FindForDocumentInDB,
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          database_.get(),
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::MessageLoopProxy::current(),
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          document_url,
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Bind(&ServiceWorkerStorage::DidFindRegistrationForDocument,
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     weak_factory_.GetWeakPtr(), document_url, callback)));
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::FindRegistrationForPattern(
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& scope,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const FindRegistrationCallback& callback) {
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!LazyInitialize(base::Bind(
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &ServiceWorkerStorage::FindRegistrationForPattern,
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          weak_factory_.GetWeakPtr(), scope, callback))) {
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (state_ != INITIALIZING || !context_) {
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CompleteFindSoon(FROM_HERE, scoped_refptr<ServiceWorkerRegistration>(),
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       SERVICE_WORKER_ERROR_FAILED, callback);
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // See if there are any stored registrations for the origin.
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!ContainsKey(registered_origins_, scope.GetOrigin())) {
1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Look for something currently being installed.
1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scoped_refptr<ServiceWorkerRegistration> installing_registration =
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FindInstallingRegistrationForPattern(scope);
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CompleteFindSoon(
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE, installing_registration,
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration ?
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        callback);
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_task_runner_->PostTask(
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &FindForPatternInDB,
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          database_.get(),
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::MessageLoopProxy::current(),
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          scope,
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Bind(&ServiceWorkerStorage::DidFindRegistrationForPattern,
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     weak_factory_.GetWeakPtr(), scope, callback)));
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ServiceWorkerStorage::FindRegistrationForId(
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    int64 registration_id,
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GURL& origin,
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const FindRegistrationCallback& callback) {
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!LazyInitialize(base::Bind(
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &ServiceWorkerStorage::FindRegistrationForId,
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          weak_factory_.GetWeakPtr(), registration_id, origin, callback))) {
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (state_ != INITIALIZING || !context_) {
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      SERVICE_WORKER_ERROR_FAILED, callback);
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // See if there are any stored registrations for the origin.
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!ContainsKey(registered_origins_, origin)) {
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Look for something currently being installed.
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<ServiceWorkerRegistration> installing_registration =
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        FindInstallingRegistrationForId(registration_id);
209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    CompleteFindNow(
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration,
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration ?
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        callback);
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<ServiceWorkerRegistration> registration =
2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      context_->GetLiveRegistration(registration_id);
2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (registration) {
2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    CompleteFindNow(registration, SERVICE_WORKER_OK, callback);
2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  database_task_runner_->PostTask(
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&FindForIdInDB,
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 database_.get(),
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::MessageLoopProxy::current(),
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 registration_id, origin,
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                            weak_factory_.GetWeakPtr(), callback)));
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerStorage::GetAllRegistrations(
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const GetAllRegistrationInfosCallback& callback) {
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!LazyInitialize(base::Bind(
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &ServiceWorkerStorage::GetAllRegistrations,
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          weak_factory_.GetWeakPtr(), callback))) {
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (state_ != INITIALIZING || !context_) {
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      RunSoon(FROM_HERE, base::Bind(
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          callback, std::vector<ServiceWorkerRegistrationInfo>()));
242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RegistrationList* registrations = new RegistrationList;
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  PostTaskAndReplyWithResult(
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      database_task_runner_,
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&ServiceWorkerDatabase::GetAllRegistrations,
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Unretained(database_.get()),
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Unretained(registrations)),
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&ServiceWorkerStorage::DidGetAllRegistrations,
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 callback,
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Owned(registrations)));
258effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
259effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerStorage::StoreRegistration(
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerRegistration* registration,
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ServiceWorkerVersion* version,
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const StatusCallback& callback) {
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(registration);
2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(version);
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(state_ == INITIALIZED || state_ == DISABLED);
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (state_ != INITIALIZED || !context_) {
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ServiceWorkerDatabase::RegistrationData data;
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.registration_id = registration->id();
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.scope = registration->pattern();
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.script = registration->script_url();
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.has_fetch_handler = true;
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.version_id = version->version_id();
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.last_update_check = base::Time::Now();
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  data.is_active = false;  // initially stored in the waiting state
2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ResourceList resources;
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  version->script_cache_map()->GetResources(&resources);
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_task_runner_->PostTask(
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&WriteRegistrationInDB,
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 database_.get(),
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::MessageLoopProxy::current(),
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 data, resources,
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            weak_factory_.GetWeakPtr(),
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            callback)));
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerStorage::UpdateToActiveState(
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ServiceWorkerRegistration* registration,
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const StatusCallback& callback) {
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(registration);
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(state_ == INITIALIZED || state_ == DISABLED);
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (state_ != INITIALIZED || !context_) {
3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PostTaskAndReplyWithResult(
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database_task_runner_,
309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ServiceWorkerDatabase::UpdateVersionToActive,
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Unretained(database_.get()),
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 registration->id(),
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 registration->script_url().GetOrigin()),
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ServiceWorkerStorage::DidUpdateToActiveState,
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 weak_factory_.GetWeakPtr(),
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 callback));
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerStorage::DeleteRegistration(
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int64 registration_id,
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GURL& origin,
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const StatusCallback& callback) {
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(state_ == INITIALIZED || state_ == DISABLED);
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (state_ != INITIALIZED || !context_) {
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  database_task_runner_->PostTask(
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&DeleteRegistrationFromDB,
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 database_.get(),
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::MessageLoopProxy::current(),
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 registration_id, origin,
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Bind(&ServiceWorkerStorage::DidDeleteRegistration,
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                            weak_factory_.GetWeakPtr(), origin, callback)));
3370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(michaeln): Either its instance should also be
3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // removed from liveregistrations map or the live object
3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // should marked as deleted in some way and not 'findable'
3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // thereafter.
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_ptr<ServiceWorkerResponseReader>
345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerStorage::CreateResponseReader(int64 response_id) {
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return make_scoped_ptr(
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new ServiceWorkerResponseReader(response_id, disk_cache()));
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_ptr<ServiceWorkerResponseWriter>
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerStorage::CreateResponseWriter(int64 response_id) {
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return make_scoped_ptr(
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new ServiceWorkerResponseWriter(response_id, disk_cache()));
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::StoreUncommittedReponseId(int64 id) {
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(kInvalidServiceWorkerResponseId, id);
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_task_runner_->PostTask(
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(base::IgnoreResult(
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &ServiceWorkerDatabase::WriteUncommittedResourceIds),
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Unretained(database_.get()),
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          std::set<int64>(&id, &id + 1)));
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::DoomUncommittedResponse(int64 id) {
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(kInvalidServiceWorkerResponseId, id);
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_task_runner_->PostTask(
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(base::IgnoreResult(
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &ServiceWorkerDatabase::PurgeUncommittedResourceIds),
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Unretained(database_.get()),
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          std::set<int64>(&id, &id + 1)));
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StartPurgingResources(std::vector<int64>(1, id));
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int64 ServiceWorkerStorage::NewRegistrationId() {
378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (state_ == DISABLED)
379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return kInvalidServiceWorkerRegistrationId;
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return next_registration_id_++;
382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int64 ServiceWorkerStorage::NewVersionId() {
385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (state_ == DISABLED)
386010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return kInvalidServiceWorkerVersionId;
387010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
388010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return next_version_id_++;
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint64 ServiceWorkerStorage::NewResourceId() {
392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (state_ == DISABLED)
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return kInvalidServiceWorkerResourceId;
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZED, state_);
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return next_resource_id_++;
3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerStorage::NotifyInstallingRegistration(
3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ServiceWorkerRegistration* registration) {
4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  installing_registrations_[registration->id()] = registration;
4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerStorage::NotifyDoneInstallingRegistration(
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ServiceWorkerRegistration* registration,
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ServiceWorkerVersion* version,
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ServiceWorkerStatusCode status) {
4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  installing_registrations_.erase(registration->id());
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != SERVICE_WORKER_OK && version) {
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ResourceList resources;
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    version->script_cache_map()->GetResources(&resources);
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::set<int64> ids;
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (size_t i = 0; i < resources.size(); ++i)
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ids.insert(resources[i].resource_id);
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    database_task_runner_->PostTask(
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(base::IgnoreResult(
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            &ServiceWorkerDatabase::PurgeUncommittedResourceIds),
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            base::Unretained(database_.get()),
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            ids));
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    StartPurgingResources(resources);
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::FilePath ServiceWorkerStorage::GetDatabasePath() {
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (path_.empty())
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return base::FilePath();
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return path_.Append(kDatabaseName);
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::FilePath ServiceWorkerStorage::GetDiskCachePath() {
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (path_.empty())
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return base::FilePath();
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return path_.Append(kDiskCacheName);
4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!context_)
441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (state_) {
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case INITIALIZED:
445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return true;
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case DISABLED:
447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return false;
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case INITIALIZING:
449010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pending_tasks_.push_back(callback);
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return false;
451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case UNINITIALIZED:
452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pending_tasks_.push_back(callback);
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Fall-through.
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  state_ = INITIALIZING;
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  database_task_runner_->PostTask(
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&ReadInitialDataFromDB,
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 database_.get(),
461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::MessageLoopProxy::current(),
462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Bind(&ServiceWorkerStorage::DidReadInitialData,
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                            weak_factory_.GetWeakPtr())));
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return false;
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerStorage::DidReadInitialData(
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    InitialData* data,
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(data);
471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(INITIALIZING, state_);
472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status == ServiceWorkerDatabase::STATUS_OK) {
474010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    next_registration_id_ = data->next_registration_id;
475010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    next_version_id_ = data->next_version_id;
476010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    next_resource_id_ = data->next_resource_id;
477010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    registered_origins_.swap(data->origins);
478010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_ = INITIALIZED;
479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(nhiroki): If status==STATUS_ERROR_CORRUPTED, do corruption recovery
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // (http://crbug.com/371675).
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DLOG(WARNING) << "Failed to initialize: " << status;
483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_ = DISABLED;
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin();
487010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != pending_tasks_.end(); ++it) {
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RunSoon(FROM_HERE, *it);
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  pending_tasks_.clear();
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::DidFindRegistrationForDocument(
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& document_url,
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const FindRegistrationCallback& callback,
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ServiceWorkerDatabase::RegistrationData& data,
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ResourceList& resources,
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status == ServiceWorkerDatabase::STATUS_OK) {
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources));
501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Look for something currently being installed.
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<ServiceWorkerRegistration> installing_registration =
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FindInstallingRegistrationForDocument(document_url);
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(installing_registration ?
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration);
511010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
512010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
513010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(nhiroki): Handle database error (http://crbug.com/371675).
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(DatabaseStatusToStatusCode(status),
516010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               scoped_refptr<ServiceWorkerRegistration>());
517010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
518010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::DidFindRegistrationForPattern(
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& scope,
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const FindRegistrationCallback& callback,
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ServiceWorkerDatabase::RegistrationData& data,
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ResourceList& resources,
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status == ServiceWorkerDatabase::STATUS_OK) {
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources));
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<ServiceWorkerRegistration> installing_registration =
532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FindInstallingRegistrationForPattern(scope);
533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(installing_registration ?
534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        installing_registration);
536010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(nhiroki): Handle database error (http://crbug.com/371675).
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(DatabaseStatusToStatusCode(status),
541010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               scoped_refptr<ServiceWorkerRegistration>());
542010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
543010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::DidFindRegistrationForId(
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const FindRegistrationCallback& callback,
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ServiceWorkerDatabase::RegistrationData& data,
547010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const ResourceList& resources,
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status == ServiceWorkerDatabase::STATUS_OK) {
550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(SERVICE_WORKER_OK,
551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 GetOrCreateRegistration(data, resources));
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(nhiroki): Handle database error (http://crbug.com/371675).
555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(DatabaseStatusToStatusCode(status),
556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               scoped_refptr<ServiceWorkerRegistration>());
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerStorage::DidGetAllRegistrations(
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GetAllRegistrationInfosCallback& callback,
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RegistrationList* registrations,
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
563010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(registrations);
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(nhiroki): Handle database error (http://crbug.com/371675).
566010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(std::vector<ServiceWorkerRegistrationInfo>());
567010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
568010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
569010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
570010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Add all stored registrations.
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::set<int64> pushed_registrations;
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<ServiceWorkerRegistrationInfo> infos;
573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (RegistrationList::const_iterator it = registrations->begin();
574010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != registrations->end(); ++it) {
57546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const bool inserted =
57646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        pushed_registrations.insert(it->registration_id).second;
57746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK(inserted);
57846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ServiceWorkerRegistration* registration =
580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        context_->GetLiveRegistration(it->registration_id);
581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (registration) {
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      infos.push_back(registration->GetInfo());
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      continue;
584010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
586010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ServiceWorkerRegistrationInfo info;
587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    info.pattern = it->scope;
588010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    info.script_url = it->script;
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    info.registration_id = it->registration_id;
59046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (ServiceWorkerVersion* version =
59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            context_->GetLiveVersion(it->version_id)) {
59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (it->is_active)
59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        info.active_version = version->GetInfo();
59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      else
59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        info.waiting_version = version->GetInfo();
596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      infos.push_back(info);
597f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
598f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (it->is_active) {
60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      info.active_version.is_null = false;
602f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      info.active_version.status = ServiceWorkerVersion::ACTIVE;
60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      info.active_version.version_id = it->version_id;
604f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      info.waiting_version.is_null = false;
606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      info.waiting_version.status = ServiceWorkerVersion::INSTALLED;
607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      info.waiting_version.version_id = it->version_id;
60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
609010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    infos.push_back(info);
610010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
611010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
612010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Add unstored registrations that are being installed.
613010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (RegistrationRefsById::const_iterator it =
614010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           installing_registrations_.begin();
615010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != installing_registrations_.end(); ++it) {
616010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (pushed_registrations.insert(it->first).second)
617010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      infos.push_back(it->second->GetInfo());
618010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
619010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
620010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  callback.Run(infos);
621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerStorage::DidStoreRegistration(
624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const StatusCallback& callback,
625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& origin,
626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<int64>& newly_purgeable_resources,
627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(nhiroki): Handle database error (http://crbug.com/371675).
630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(DatabaseStatusToStatusCode(status));
631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
632010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
633010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  registered_origins_.insert(origin);
634010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  callback.Run(SERVICE_WORKER_OK);
635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StartPurgingResources(newly_purgeable_resources);
636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::DidUpdateToActiveState(
639cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const StatusCallback& callback,
640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(nhiroki): Handle database error (http://crbug.com/371675).
642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(DatabaseStatusToStatusCode(status));
643010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
644010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
645010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ServiceWorkerStorage::DidDeleteRegistration(
646010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GURL& origin,
647010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const StatusCallback& callback,
648010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool origin_is_deletable,
649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<int64>& newly_purgeable_resources,
650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase::Status status) {
651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(nhiroki): Handle database error (http://crbug.com/371675).
653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(DatabaseStatusToStatusCode(status));
654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
656010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (origin_is_deletable)
657010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    registered_origins_.erase(origin);
658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(SERVICE_WORKER_OK);
659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StartPurgingResources(newly_purgeable_resources);
660010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
661010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
6620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_refptr<ServiceWorkerRegistration>
663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ServiceWorkerStorage::GetOrCreateRegistration(
664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ServiceWorkerDatabase::RegistrationData& data,
665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ResourceList& resources) {
666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<ServiceWorkerRegistration> registration =
667cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      context_->GetLiveRegistration(data.registration_id);
668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (registration)
669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return registration;
6700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registration = new ServiceWorkerRegistration(
672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      data.scope, data.script, data.registration_id, context_);
6730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<ServiceWorkerVersion> version =
674010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      context_->GetLiveVersion(data.version_id);
6750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!version) {
676010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    version = new ServiceWorkerVersion(registration, data.version_id, context_);
677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    version->SetStatus(data.is_active ?
678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ServiceWorkerVersion::ACTIVE : ServiceWorkerVersion::INSTALLED);
679cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    version->script_cache_map()->SetResources(resources);
6800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
6820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (version->status() == ServiceWorkerVersion::ACTIVE)
6830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    registration->set_active_version(version);
6840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else if (version->status() == ServiceWorkerVersion::INSTALLED)
685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    registration->set_waiting_version(version);
6860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
6870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    NOTREACHED();
6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(michaeln): Hmmm, what if DeleteReg was invoked after
6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // the Find result we're returning here? NOTREACHED condition?
6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return registration;
6910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
6920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
6930529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegistration*
6940529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::FindInstallingRegistrationForDocument(
6950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const GURL& document_url) {
69646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!document_url.has_ref());
69746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
69846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  LongestScopeMatcher matcher(document_url);
69946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ServiceWorkerRegistration* match = NULL;
70046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
70146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // TODO(nhiroki): This searches over installing registrations linearly and it
70246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // couldn't be scalable. Maybe the regs should be partitioned by origin.
7030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (RegistrationRefsById::const_iterator it =
7040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch           installing_registrations_.begin();
7050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       it != installing_registrations_.end(); ++it) {
70646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (matcher.MatchLongest(it->second->pattern()))
70746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      match = it->second;
7080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
70946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return match;
7100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
7110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
7120529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegistration*
7130529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::FindInstallingRegistrationForPattern(
7140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const GURL& scope) {
7150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (RegistrationRefsById::const_iterator it =
7160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch           installing_registrations_.begin();
7170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       it != installing_registrations_.end(); ++it) {
7180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (it->second->pattern() == scope)
7190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return it->second;
7200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
7210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return NULL;
7220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
7230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
7240529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegistration*
7250529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerStorage::FindInstallingRegistrationForId(
7260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int64 registration_id) {
7270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RegistrationRefsById::const_iterator found =
7280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      installing_registrations_.find(registration_id);
7290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (found == installing_registrations_.end())
7300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
7310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return found->second;
7320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
7330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
734010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
735010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (disk_cache_)
736010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return disk_cache_.get();
737010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
738010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  disk_cache_.reset(new ServiceWorkerDiskCache);
739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath path = GetDiskCachePath();
741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (path.empty()) {
742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int rv = disk_cache_->InitWithMemBackend(
743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        kMaxMemDiskCacheSize,
744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&EmptyCompletionCallback));
745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_EQ(net::OK, rv);
746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return disk_cache_.get();
747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = disk_cache_->InitWithDiskBackend(
750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      path, kMaxDiskCacheSize, false,
751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      disk_cache_thread_.get(),
752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized,
753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 weak_factory_.GetWeakPtr()));
754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv != net::ERR_IO_PENDING)
755cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnDiskCacheInitialized(rv);
756cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
757010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return disk_cache_.get();
758010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
759010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::OnDiskCacheInitialized(int rv) {
761cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv != net::OK) {
762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Failed to open the serviceworker diskcache: "
763cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               << net::ErrorToString(rv);
764cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(michaeln): DeleteAndStartOver()
765cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    disk_cache_->Disable();
766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    state_ = DISABLED;
767cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ServiceWorkerHistograms::CountInitDiskCacheResult(rv == net::OK);
769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
771cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::StartPurgingResources(
772cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<int64>& ids) {
773cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < ids.size(); ++i)
774cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    purgeable_reource_ids_.push_back(ids[i]);
775cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ContinuePurgingResources();
776cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
777cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
778cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::StartPurgingResources(
779cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ResourceList& resources) {
780cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < resources.size(); ++i)
781cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    purgeable_reource_ids_.push_back(resources[i].resource_id);
782cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ContinuePurgingResources();
783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::ContinuePurgingResources() {
786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (purgeable_reource_ids_.empty() || is_purge_pending_)
787cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
788cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
789cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Do one at a time until we're done, use RunSoon to avoid recursion when
790cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // DoomEntry returns immediately.
791cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  is_purge_pending_ = true;
792cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int64 id = purgeable_reource_ids_.front();
793cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  purgeable_reource_ids_.pop_front();
794cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RunSoon(FROM_HERE,
795cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Bind(&ServiceWorkerStorage::PurgeResource,
796cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     weak_factory_.GetWeakPtr(), id));
797cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
798cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
799cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::PurgeResource(int64 id) {
800cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(is_purge_pending_);
801cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = disk_cache()->DoomEntry(
802cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      id, base::Bind(&ServiceWorkerStorage::OnResourcePurged,
803cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     weak_factory_.GetWeakPtr(), id));
804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv != net::ERR_IO_PENDING)
805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnResourcePurged(id, rv);
806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::OnResourcePurged(int64 id, int rv) {
809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(is_purge_pending_);
810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  is_purge_pending_ = false;
811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  database_task_runner_->PostTask(
813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(base::IgnoreResult(
815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          &ServiceWorkerDatabase::ClearPurgeableResourceIds),
816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Unretained(database_.get()),
817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          std::set<int64>(&id, &id + 1)));
818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
819cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ContinuePurgingResources();
820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
821cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::ReadInitialDataFromDB(
823cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase* database,
824cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
825cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const InitializeCallback& callback) {
826cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(database);
827cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<ServiceWorkerStorage::InitialData> data(
828cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new ServiceWorkerStorage::InitialData());
829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
830cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::Status status =
831cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database->GetNextAvailableIds(&data->next_registration_id,
832cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    &data->next_version_id,
833cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    &data->next_resource_id);
834cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    original_task_runner->PostTask(
836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
839cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
840cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  status = database->GetOriginsWithRegistrations(&data->origins);
841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  original_task_runner->PostTask(
842cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
843cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
844cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
845cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::DeleteRegistrationFromDB(
846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase* database,
847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 registration_id,
849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& origin,
850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const DeleteRegistrationCallback& callback) {
851cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(database);
852cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<int64> newly_purgeable_resources;
854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::Status status =
855cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database->DeleteRegistration(registration_id, origin,
856cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   &newly_purgeable_resources);
857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    original_task_runner->PostTask(
859cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status));
860cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
861cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the
864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // unique origin list.
865cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<ServiceWorkerDatabase::RegistrationData> registrations;
866cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  status = database->GetRegistrationsForOrigin(origin, &registrations);
867cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
868cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    original_task_runner->PostTask(
869cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status));
870cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
871cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
872cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
873cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool deletable = registrations.empty();
874cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  original_task_runner->PostTask(
875cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE, base::Bind(callback, deletable,
876cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            newly_purgeable_resources, status));
877cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
878cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
879cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::WriteRegistrationInDB(
880cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase* database,
881cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
882cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ServiceWorkerDatabase::RegistrationData& data,
883cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ResourceList& resources,
884cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const WriteRegistrationCallback& callback) {
885cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(database);
886cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<int64> newly_purgeable_resources;
887cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::Status status =
888cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database->WriteRegistration(data, resources, &newly_purgeable_resources);
889cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  original_task_runner->PostTask(
890cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
891cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(callback, data.script.GetOrigin(),
892cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 newly_purgeable_resources, status));
893cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
894cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
895cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::FindForDocumentInDB(
896cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase* database,
897cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
898cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& document_url,
899cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const FindInDBCallback& callback) {
900cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL origin = document_url.GetOrigin();
901cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegistrationList registrations;
902cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::Status status =
903cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database->GetRegistrationsForOrigin(origin, &registrations);
904cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
905cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    original_task_runner->PostTask(
906cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
907cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(callback,
908cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   ServiceWorkerDatabase::RegistrationData(),
909cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   ResourceList(),
910cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   status));
911cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
912cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
913cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
914cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::RegistrationData data;
915cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResourceList resources;
916cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  status = ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
91746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
91846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Find one with a pattern match.
91946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  LongestScopeMatcher matcher(document_url);
92046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int64 match = kInvalidServiceWorkerRegistrationId;
92146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < registrations.size(); ++i) {
92246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (matcher.MatchLongest(registrations[i].scope))
92346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      match = registrations[i].registration_id;
924cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
925cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
92646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (match != kInvalidServiceWorkerRegistrationId)
92746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    status = database->ReadRegistration(match, origin, &data, &resources);
92846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
929cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  original_task_runner->PostTask(
930cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
931cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(callback, data, resources, status));
932cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
933cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
934cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::FindForPatternInDB(
935cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase* database,
936cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
937cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& scope,
938cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const FindInDBCallback& callback) {
939cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL origin = scope.GetOrigin();
940cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<ServiceWorkerDatabase::RegistrationData> registrations;
941cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::Status status =
942cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database->GetRegistrationsForOrigin(origin, &registrations);
943cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status != ServiceWorkerDatabase::STATUS_OK) {
944cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    original_task_runner->PostTask(
945cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
946cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(callback,
947cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   ServiceWorkerDatabase::RegistrationData(),
948cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   ResourceList(),
949cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   status));
950cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
951cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
952cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
953cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Find one with an exact matching scope.
954cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::RegistrationData data;
955cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResourceList resources;
956cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  status = ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
957cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (RegistrationList::const_iterator it = registrations.begin();
958cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != registrations.end(); ++it) {
959cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (scope != it->scope)
960cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
961cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    status = database->ReadRegistration(it->registration_id, origin,
962cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        &data, &resources);
963cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    break;  // We're done looping.
964cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
965cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
966cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  original_task_runner->PostTask(
967cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
968cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(callback, data, resources, status));
969cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
970cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
971cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerStorage::FindForIdInDB(
972cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerDatabase* database,
973cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
974cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 registration_id,
975cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GURL& origin,
976cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const FindInDBCallback& callback) {
977cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::RegistrationData data;
978cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResourceList resources;
979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ServiceWorkerDatabase::Status status =
980cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database->ReadRegistration(registration_id, origin, &data, &resources);
981cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  original_task_runner->PostTask(
982cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE, base::Bind(callback, data, resources, status));
983cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
984cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
985a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace content
986