Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / child / service_worker / service_worker_provider_context.cc
blobd8273aaef4607725d961b6f3a48340f38e9825d5
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"
7 #include "base/bind.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"
18 namespace content {
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());
29 DCHECK(dispatcher);
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_);
50 if (!registration_)
51 return false;
53 *info = registration_->info();
54 if (installing_)
55 attrs->installing = installing_->info();
56 if (waiting_)
57 attrs->waiting = waiting_->info();
58 if (active_)
59 attrs->active = active_->info();
60 return true;
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());
107 controller_.reset();
108 active_.reset();
109 waiting_.reset();
110 installing_.reset();
111 registration_.reset();
114 void ServiceWorkerProviderContext::OnServiceWorkerStateChanged(
115 int handle_id,
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
131 // this provider.
132 DCHECK(which);
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.
147 controller_ =
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)) {
187 return;
189 delete this;
192 } // namespace content