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/message_loop/message_loop_proxy.h"
9 #include "base/stl_util.h"
10 #include "content/child/child_thread_impl.h"
11 #include "content/child/service_worker/service_worker_dispatcher.h"
12 #include "content/child/service_worker/service_worker_handle_reference.h"
13 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
14 #include "content/child/thread_safe_sender.h"
15 #include "content/child/worker_task_runner.h"
16 #include "content/common/service_worker/service_worker_messages.h"
20 ServiceWorkerProviderContext::ServiceWorkerProviderContext(int provider_id
)
21 : provider_id_(provider_id
),
22 main_thread_loop_proxy_(base::MessageLoopProxy::current()) {
23 if (!ChildThreadImpl::current())
24 return; // May be null in some tests.
25 thread_safe_sender_
= ChildThreadImpl::current()->thread_safe_sender();
26 ServiceWorkerDispatcher
* dispatcher
=
27 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
28 thread_safe_sender_
.get());
30 dispatcher
->AddProviderContext(this);
33 ServiceWorkerProviderContext::~ServiceWorkerProviderContext() {
34 if (ServiceWorkerDispatcher
* dispatcher
=
35 ServiceWorkerDispatcher::GetThreadSpecificInstance()) {
36 // Remove this context from the dispatcher living on the main thread.
37 dispatcher
->RemoveProviderContext(this);
41 ServiceWorkerHandleReference
* ServiceWorkerProviderContext::controller() {
42 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
43 return controller_
.get();
46 bool ServiceWorkerProviderContext::GetRegistrationInfoAndVersionAttributes(
47 ServiceWorkerRegistrationObjectInfo
* info
,
48 ServiceWorkerVersionAttributes
* attrs
) {
49 base::AutoLock
lock(lock_
);
53 *info
= registration_
->info();
55 attrs
->installing
= installing_
->info();
57 attrs
->waiting
= waiting_
->info();
59 attrs
->active
= active_
->info();
63 void ServiceWorkerProviderContext::SetVersionAttributes(
64 ChangedVersionAttributesMask mask
,
65 const ServiceWorkerVersionAttributes
& attrs
) {
66 base::AutoLock
lock(lock_
);
67 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
68 DCHECK(registration_
);
70 if (mask
.installing_changed()) {
71 installing_
= ServiceWorkerHandleReference::Adopt(
72 attrs
.installing
, thread_safe_sender_
.get());
74 if (mask
.waiting_changed()) {
75 waiting_
= ServiceWorkerHandleReference::Adopt(
76 attrs
.waiting
, thread_safe_sender_
.get());
78 if (mask
.active_changed()) {
79 active_
= ServiceWorkerHandleReference::Adopt(
80 attrs
.active
, thread_safe_sender_
.get());
84 void ServiceWorkerProviderContext::OnAssociateRegistration(
85 const ServiceWorkerRegistrationObjectInfo
& info
,
86 const ServiceWorkerVersionAttributes
& attrs
) {
87 base::AutoLock
lock(lock_
);
88 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
89 DCHECK(!registration_
);
90 DCHECK_NE(kInvalidServiceWorkerRegistrationId
, info
.registration_id
);
91 DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId
, info
.handle_id
);
93 registration_
= ServiceWorkerRegistrationHandleReference::Adopt(
94 info
, thread_safe_sender_
.get());
95 installing_
= ServiceWorkerHandleReference::Adopt(
96 attrs
.installing
, thread_safe_sender_
.get());
97 waiting_
= ServiceWorkerHandleReference::Adopt(
98 attrs
.waiting
, thread_safe_sender_
.get());
99 active_
= ServiceWorkerHandleReference::Adopt(
100 attrs
.active
, thread_safe_sender_
.get());
103 void ServiceWorkerProviderContext::OnDisassociateRegistration() {
104 base::AutoLock
lock(lock_
);
105 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
111 registration_
.reset();
114 void ServiceWorkerProviderContext::OnServiceWorkerStateChanged(
116 blink::WebServiceWorkerState state
) {
117 base::AutoLock
lock(lock_
);
118 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
120 ServiceWorkerHandleReference
* which
= NULL
;
121 if (handle_id
== controller_handle_id())
122 which
= controller_
.get();
123 else if (handle_id
== active_handle_id())
124 which
= active_
.get();
125 else if (handle_id
== waiting_handle_id())
126 which
= waiting_
.get();
127 else if (handle_id
== installing_handle_id())
128 which
= installing_
.get();
130 // We should only get messages for ServiceWorkers associated with
134 which
->set_state(state
);
136 // TODO(kinuko): We can forward the message to other threads here
137 // when we support navigator.serviceWorker in dedicated workers.
140 void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
141 const ServiceWorkerObjectInfo
& info
) {
142 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
143 DCHECK(registration_
);
145 // This context is is the primary owner of this handle, keeps the
146 // initial reference until it goes away.
148 ServiceWorkerHandleReference::Adopt(info
, thread_safe_sender_
.get());
150 // TODO(kinuko): We can forward the message to other threads here
151 // when we support navigator.serviceWorker in dedicated workers.
154 int ServiceWorkerProviderContext::installing_handle_id() const {
155 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
156 return installing_
? installing_
->info().handle_id
157 : kInvalidServiceWorkerHandleId
;
160 int ServiceWorkerProviderContext::waiting_handle_id() const {
161 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
162 return waiting_
? waiting_
->info().handle_id
163 : kInvalidServiceWorkerHandleId
;
166 int ServiceWorkerProviderContext::active_handle_id() const {
167 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
168 return active_
? active_
->info().handle_id
169 : kInvalidServiceWorkerHandleId
;
172 int ServiceWorkerProviderContext::controller_handle_id() const {
173 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
174 return controller_
? controller_
->info().handle_id
175 : kInvalidServiceWorkerHandleId
;
178 int ServiceWorkerProviderContext::registration_handle_id() const {
179 DCHECK(main_thread_loop_proxy_
->RunsTasksOnCurrentThread());
180 return registration_
? registration_
->info().handle_id
181 : kInvalidServiceWorkerRegistrationHandleId
;
184 void ServiceWorkerProviderContext::DestructOnMainThread() const {
185 if (!main_thread_loop_proxy_
->RunsTasksOnCurrentThread() &&
186 main_thread_loop_proxy_
->DeleteSoon(FROM_HERE
, this)) {
192 } // namespace content