1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/service_worker/service_worker_provider_context.h"
8 #include "base/location.h"
9 #include "base/stl_util.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/child/child_thread_impl.h"
12 #include "content/child/service_worker/service_worker_dispatcher.h"
13 #include "content/child/service_worker/service_worker_handle_reference.h"
14 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
15 #include "content/child/thread_safe_sender.h"
16 #include "content/child/worker_task_runner.h"
17 #include "content/common/service_worker/service_worker_messages.h"
21 ServiceWorkerProviderContext::ServiceWorkerProviderContext(int provider_id
)
22 : provider_id_(provider_id
),
23 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
24 if (!ChildThreadImpl::current())
25 return; // May be null in some tests.
26 thread_safe_sender_
= ChildThreadImpl::current()->thread_safe_sender();
27 ServiceWorkerDispatcher
* dispatcher
=
28 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
29 thread_safe_sender_
.get());
31 dispatcher
->AddProviderContext(this);
34 ServiceWorkerProviderContext::~ServiceWorkerProviderContext() {
35 if (ServiceWorkerDispatcher
* dispatcher
=
36 ServiceWorkerDispatcher::GetThreadSpecificInstance()) {
37 // Remove this context from the dispatcher living on the main thread.
38 dispatcher
->RemoveProviderContext(this);
42 ServiceWorkerHandleReference
* ServiceWorkerProviderContext::controller() {
43 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
44 return controller_
.get();
47 bool ServiceWorkerProviderContext::GetRegistrationInfoAndVersionAttributes(
48 ServiceWorkerRegistrationObjectInfo
* info
,
49 ServiceWorkerVersionAttributes
* attrs
) {
50 base::AutoLock
lock(lock_
);
54 *info
= registration_
->info();
56 attrs
->installing
= installing_
->info();
58 attrs
->waiting
= waiting_
->info();
60 attrs
->active
= active_
->info();
64 void ServiceWorkerProviderContext::SetVersionAttributes(
65 ChangedVersionAttributesMask mask
,
66 const ServiceWorkerVersionAttributes
& attrs
) {
67 base::AutoLock
lock(lock_
);
68 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
69 DCHECK(registration_
);
71 if (mask
.installing_changed()) {
72 installing_
= ServiceWorkerHandleReference::Adopt(
73 attrs
.installing
, thread_safe_sender_
.get());
75 if (mask
.waiting_changed()) {
76 waiting_
= ServiceWorkerHandleReference::Adopt(
77 attrs
.waiting
, thread_safe_sender_
.get());
79 if (mask
.active_changed()) {
80 active_
= ServiceWorkerHandleReference::Adopt(
81 attrs
.active
, thread_safe_sender_
.get());
85 void ServiceWorkerProviderContext::OnAssociateRegistration(
86 const ServiceWorkerRegistrationObjectInfo
& info
,
87 const ServiceWorkerVersionAttributes
& attrs
) {
88 base::AutoLock
lock(lock_
);
89 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
90 DCHECK(!registration_
);
91 DCHECK_NE(kInvalidServiceWorkerRegistrationId
, info
.registration_id
);
92 DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId
, info
.handle_id
);
94 registration_
= ServiceWorkerRegistrationHandleReference::Adopt(
95 info
, thread_safe_sender_
.get());
96 installing_
= ServiceWorkerHandleReference::Adopt(
97 attrs
.installing
, thread_safe_sender_
.get());
98 waiting_
= ServiceWorkerHandleReference::Adopt(
99 attrs
.waiting
, thread_safe_sender_
.get());
100 active_
= ServiceWorkerHandleReference::Adopt(
101 attrs
.active
, thread_safe_sender_
.get());
104 void ServiceWorkerProviderContext::OnDisassociateRegistration() {
105 base::AutoLock
lock(lock_
);
106 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
112 registration_
.reset();
115 void ServiceWorkerProviderContext::OnServiceWorkerStateChanged(
117 blink::WebServiceWorkerState state
) {
118 base::AutoLock
lock(lock_
);
119 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
121 ServiceWorkerHandleReference
* which
= NULL
;
122 if (handle_id
== controller_handle_id())
123 which
= controller_
.get();
124 else if (handle_id
== active_handle_id())
125 which
= active_
.get();
126 else if (handle_id
== waiting_handle_id())
127 which
= waiting_
.get();
128 else if (handle_id
== installing_handle_id())
129 which
= installing_
.get();
131 // We should only get messages for ServiceWorkers associated with
135 which
->set_state(state
);
137 // TODO(kinuko): We can forward the message to other threads here
138 // when we support navigator.serviceWorker in dedicated workers.
141 void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
142 const ServiceWorkerObjectInfo
& info
) {
143 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
144 DCHECK(registration_
);
146 // This context is is the primary owner of this handle, keeps the
147 // initial reference until it goes away.
149 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
151 // TODO(kinuko): We can forward the message to other threads here
152 // when we support navigator.serviceWorker in dedicated workers.
155 int ServiceWorkerProviderContext::installing_handle_id() const {
156 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
157 return installing_
? installing_
->info().handle_id
158 : kInvalidServiceWorkerHandleId
;
161 int ServiceWorkerProviderContext::waiting_handle_id() const {
162 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
163 return waiting_
? waiting_
->info().handle_id
164 : kInvalidServiceWorkerHandleId
;
167 int ServiceWorkerProviderContext::active_handle_id() const {
168 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
169 return active_
? active_
->info().handle_id
170 : kInvalidServiceWorkerHandleId
;
173 int ServiceWorkerProviderContext::controller_handle_id() const {
174 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
175 return controller_
? controller_
->info().handle_id
176 : kInvalidServiceWorkerHandleId
;
179 int ServiceWorkerProviderContext::registration_handle_id() const {
180 DCHECK(main_thread_task_runner_
->RunsTasksOnCurrentThread());
181 return registration_
? registration_
->info().handle_id
182 : kInvalidServiceWorkerRegistrationHandleId
;
185 void ServiceWorkerProviderContext::DestructOnMainThread() const {
186 if (!main_thread_task_runner_
->RunsTasksOnCurrentThread() &&
187 main_thread_task_runner_
->DeleteSoon(FROM_HERE
, this)) {
193 } // namespace content