service_worker_context_wrapper.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/service_worker/service_worker_context_wrapper.h"
6
7#include "base/files/file_path.h"
8#include "base/logging.h"
9#include "base/threading/sequenced_worker_pool.h"
10#include "content/browser/service_worker/service_worker_context_core.h"
11#include "content/browser/service_worker/service_worker_context_observer.h"
12#include "content/browser/service_worker/service_worker_process_manager.h"
13#include "content/public/browser/browser_thread.h"
14#include "webkit/browser/quota/quota_manager_proxy.h"
15
16namespace content {
17
18ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
19    BrowserContext* browser_context)
20    : observer_list_(
21          new ObserverListThreadSafe<ServiceWorkerContextObserver>()),
22      process_manager_(new ServiceWorkerProcessManager(browser_context)),
23      is_incognito_(false) {
24}
25
26ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
27}
28
29void ServiceWorkerContextWrapper::Init(
30    const base::FilePath& user_data_directory,
31    quota::QuotaManagerProxy* quota_manager_proxy) {
32  is_incognito_ = user_data_directory.empty();
33  scoped_refptr<base::SequencedTaskRunner> database_task_runner =
34      BrowserThread::GetBlockingPool()->
35          GetSequencedTaskRunnerWithShutdownBehavior(
36              BrowserThread::GetBlockingPool()->GetSequenceToken(),
37              base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
38  scoped_refptr<base::MessageLoopProxy> disk_cache_thread =
39      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE);
40  scoped_refptr<base::SequencedTaskRunner> stores_task_runner =
41      BrowserThread::GetBlockingPool()
42          ->GetSequencedTaskRunnerWithShutdownBehavior(
43              BrowserThread::GetBlockingPool()->GetSequenceToken(),
44              base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
45  InitInternal(user_data_directory,
46               stores_task_runner,
47               database_task_runner,
48               disk_cache_thread,
49               quota_manager_proxy);
50}
51
52void ServiceWorkerContextWrapper::Shutdown() {
53  DCHECK_CURRENTLY_ON(BrowserThread::UI);
54  process_manager_->Shutdown();
55  BrowserThread::PostTask(
56      BrowserThread::IO,
57      FROM_HERE,
58      base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
59}
60
61void ServiceWorkerContextWrapper::DeleteAndStartOver() {
62  DCHECK_CURRENTLY_ON(BrowserThread::IO);
63  context_core_->DeleteAndStartOver(
64      base::Bind(&ServiceWorkerContextWrapper::DidDeleteAndStartOver, this));
65}
66
67ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
68  DCHECK_CURRENTLY_ON(BrowserThread::IO);
69  return context_core_.get();
70}
71
72static void FinishRegistrationOnIO(
73    const ServiceWorkerContext::ResultCallback& continuation,
74    ServiceWorkerStatusCode status,
75    int64 registration_id,
76    int64 version_id) {
77  DCHECK_CURRENTLY_ON(BrowserThread::IO);
78  BrowserThread::PostTask(
79      BrowserThread::UI,
80      FROM_HERE,
81      base::Bind(continuation, status == SERVICE_WORKER_OK));
82}
83
84void ServiceWorkerContextWrapper::RegisterServiceWorker(
85    const GURL& pattern,
86    const GURL& script_url,
87    const ResultCallback& continuation) {
88  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
89    BrowserThread::PostTask(
90        BrowserThread::IO,
91        FROM_HERE,
92        base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker,
93                   this,
94                   pattern,
95                   script_url,
96                   continuation));
97    return;
98  }
99
100  context()->RegisterServiceWorker(
101      pattern,
102      script_url,
103      -1,
104      NULL /* provider_host */,
105      base::Bind(&FinishRegistrationOnIO, continuation));
106}
107
108static void FinishUnregistrationOnIO(
109    const ServiceWorkerContext::ResultCallback& continuation,
110    ServiceWorkerStatusCode status) {
111  DCHECK_CURRENTLY_ON(BrowserThread::IO);
112  BrowserThread::PostTask(
113      BrowserThread::UI,
114      FROM_HERE,
115      base::Bind(continuation, status == SERVICE_WORKER_OK));
116}
117
118void ServiceWorkerContextWrapper::UnregisterServiceWorker(
119    const GURL& pattern,
120    const ResultCallback& continuation) {
121  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
122    BrowserThread::PostTask(
123        BrowserThread::IO,
124        FROM_HERE,
125        base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
126                   this,
127                   pattern,
128                   continuation));
129    return;
130  }
131
132  context()->UnregisterServiceWorker(
133      pattern,
134      base::Bind(&FinishUnregistrationOnIO, continuation));
135}
136
137void ServiceWorkerContextWrapper::Terminate() {
138  DCHECK_CURRENTLY_ON(BrowserThread::UI);
139  process_manager_->Shutdown();
140}
141
142void ServiceWorkerContextWrapper::AddObserver(
143    ServiceWorkerContextObserver* observer) {
144  observer_list_->AddObserver(observer);
145}
146
147void ServiceWorkerContextWrapper::RemoveObserver(
148    ServiceWorkerContextObserver* observer) {
149  observer_list_->RemoveObserver(observer);
150}
151
152void ServiceWorkerContextWrapper::InitInternal(
153    const base::FilePath& user_data_directory,
154    base::SequencedTaskRunner* stores_task_runner,
155    base::SequencedTaskRunner* database_task_runner,
156    base::MessageLoopProxy* disk_cache_thread,
157    quota::QuotaManagerProxy* quota_manager_proxy) {
158  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
159    BrowserThread::PostTask(
160        BrowserThread::IO,
161        FROM_HERE,
162        base::Bind(&ServiceWorkerContextWrapper::InitInternal,
163                   this,
164                   user_data_directory,
165                   make_scoped_refptr(stores_task_runner),
166                   make_scoped_refptr(database_task_runner),
167                   make_scoped_refptr(disk_cache_thread),
168                   make_scoped_refptr(quota_manager_proxy)));
169    return;
170  }
171  DCHECK(!context_core_);
172  context_core_.reset(new ServiceWorkerContextCore(user_data_directory,
173                                                   stores_task_runner,
174                                                   database_task_runner,
175                                                   disk_cache_thread,
176                                                   quota_manager_proxy,
177                                                   observer_list_,
178                                                   this));
179}
180
181void ServiceWorkerContextWrapper::ShutdownOnIO() {
182  DCHECK_CURRENTLY_ON(BrowserThread::IO);
183  context_core_.reset();
184}
185
186void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
187    ServiceWorkerStatusCode status) {
188  DCHECK_CURRENTLY_ON(BrowserThread::IO);
189  if (status != SERVICE_WORKER_OK) {
190    context_core_.reset();
191    return;
192  }
193  context_core_.reset(new ServiceWorkerContextCore(context_core_.get(), this));
194  DVLOG(1) << "Restarted ServiceWorkerContextCore successfully.";
195}
196
197}  // namespace content
198