Apply _RELATIVE relocations ahead of others.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_provider_host.cc
blobe16454558e0ec9cc46862b3110a811dcf3bfca6f
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.
5 #include "content/browser/service_worker/service_worker_provider_host.h"
7 #include "base/stl_util.h"
8 #include "content/browser/message_port_message_filter.h"
9 #include "content/browser/service_worker/service_worker_context_core.h"
10 #include "content/browser/service_worker/service_worker_context_request_handler.h"
11 #include "content/browser/service_worker/service_worker_controllee_request_handler.h"
12 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
13 #include "content/browser/service_worker/service_worker_handle.h"
14 #include "content/browser/service_worker/service_worker_registration_handle.h"
15 #include "content/browser/service_worker/service_worker_utils.h"
16 #include "content/browser/service_worker/service_worker_version.h"
17 #include "content/common/resource_request_body.h"
18 #include "content/common/service_worker/service_worker_messages.h"
19 #include "content/common/service_worker/service_worker_types.h"
21 namespace content {
23 static const int kDocumentMainThreadId = 0;
25 ServiceWorkerProviderHost::ServiceWorkerProviderHost(
26 int process_id, int provider_id,
27 base::WeakPtr<ServiceWorkerContextCore> context,
28 ServiceWorkerDispatcherHost* dispatcher_host)
29 : process_id_(process_id),
30 provider_id_(provider_id),
31 context_(context),
32 dispatcher_host_(dispatcher_host),
33 allow_association_(true) {
36 ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
37 // Clear docurl so the deferred activation of a waiting worker
38 // won't associate the new version with a provider being destroyed.
39 document_url_ = GURL();
40 if (controlling_version_.get())
41 controlling_version_->RemoveControllee(this);
42 if (associated_registration_.get()) {
43 DecreaseProcessReference(associated_registration_->pattern());
44 associated_registration_->RemoveListener(this);
46 for (std::vector<GURL>::iterator it = associated_patterns_.begin();
47 it != associated_patterns_.end(); ++it) {
48 DecreaseProcessReference(*it);
52 void ServiceWorkerProviderHost::OnRegistrationFailed(
53 ServiceWorkerRegistration* registration) {
54 DCHECK_EQ(associated_registration_.get(), registration);
55 DisassociateRegistration();
58 void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
59 DCHECK(!url.has_ref());
60 document_url_ = url;
63 void ServiceWorkerProviderHost::SetTopmostFrameUrl(const GURL& url) {
64 topmost_frame_url_ = url;
67 void ServiceWorkerProviderHost::SetControllerVersionAttribute(
68 ServiceWorkerVersion* version) {
69 if (version == controlling_version_.get())
70 return;
72 scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_;
73 controlling_version_ = version;
74 if (version)
75 version->AddControllee(this);
76 if (previous_version.get())
77 previous_version->RemoveControllee(this);
79 if (!dispatcher_host_)
80 return; // Could be NULL in some tests.
82 dispatcher_host_->Send(new ServiceWorkerMsg_SetControllerServiceWorker(
83 kDocumentMainThreadId, provider_id(), CreateHandleAndPass(version)));
86 bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) {
87 if (!context_)
88 return true; // System is shutting down.
89 if (active_version())
90 return false; // Unexpected bad message.
92 ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id);
93 if (!live_version)
94 return true; // Was deleted before it got started.
96 ServiceWorkerVersionInfo info = live_version->GetInfo();
97 if (info.running_status != ServiceWorkerVersion::STARTING ||
98 info.process_id != process_id_) {
99 // If we aren't trying to start this version in our process
100 // something is amiss.
101 return false;
104 running_hosted_version_ = live_version;
105 return true;
108 void ServiceWorkerProviderHost::AssociateRegistration(
109 ServiceWorkerRegistration* registration) {
110 DCHECK(CanAssociateRegistration(registration));
111 if (associated_registration_.get())
112 DecreaseProcessReference(associated_registration_->pattern());
113 IncreaseProcessReference(registration->pattern());
115 if (dispatcher_host_) {
116 ServiceWorkerRegistrationHandle* handle =
117 dispatcher_host_->GetOrCreateRegistrationHandle(
118 provider_id(), registration);
120 ServiceWorkerVersionAttributes attrs;
121 attrs.installing = handle->CreateServiceWorkerHandleAndPass(
122 registration->installing_version());
123 attrs.waiting = handle->CreateServiceWorkerHandleAndPass(
124 registration->waiting_version());
125 attrs.active = handle->CreateServiceWorkerHandleAndPass(
126 registration->active_version());
128 dispatcher_host_->Send(new ServiceWorkerMsg_AssociateRegistration(
129 kDocumentMainThreadId, provider_id(), handle->GetObjectInfo(), attrs));
132 associated_registration_ = registration;
133 associated_registration_->AddListener(this);
134 SetControllerVersionAttribute(registration->active_version());
137 void ServiceWorkerProviderHost::DisassociateRegistration() {
138 if (!associated_registration_.get())
139 return;
140 DecreaseProcessReference(associated_registration_->pattern());
141 associated_registration_->RemoveListener(this);
142 associated_registration_ = NULL;
143 SetControllerVersionAttribute(NULL);
145 if (dispatcher_host_) {
146 dispatcher_host_->Send(new ServiceWorkerMsg_DisassociateRegistration(
147 kDocumentMainThreadId, provider_id()));
151 scoped_ptr<ServiceWorkerRequestHandler>
152 ServiceWorkerProviderHost::CreateRequestHandler(
153 FetchRequestMode request_mode,
154 FetchCredentialsMode credentials_mode,
155 ResourceType resource_type,
156 RequestContextType request_context_type,
157 RequestContextFrameType frame_type,
158 base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
159 scoped_refptr<ResourceRequestBody> body) {
160 if (IsHostToRunningServiceWorker()) {
161 return scoped_ptr<ServiceWorkerRequestHandler>(
162 new ServiceWorkerContextRequestHandler(
163 context_, AsWeakPtr(), blob_storage_context, resource_type));
165 if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
166 controlling_version()) {
167 return scoped_ptr<ServiceWorkerRequestHandler>(
168 new ServiceWorkerControlleeRequestHandler(context_,
169 AsWeakPtr(),
170 blob_storage_context,
171 request_mode,
172 credentials_mode,
173 resource_type,
174 request_context_type,
175 frame_type,
176 body));
178 return scoped_ptr<ServiceWorkerRequestHandler>();
181 bool ServiceWorkerProviderHost::CanAssociateRegistration(
182 ServiceWorkerRegistration* registration) {
183 if (!context_)
184 return false;
185 if (running_hosted_version_.get())
186 return false;
187 if (!registration || associated_registration_.get() || !allow_association_)
188 return false;
189 return true;
192 void ServiceWorkerProviderHost::PostMessage(
193 const base::string16& message,
194 const std::vector<int>& sent_message_port_ids) {
195 if (!dispatcher_host_)
196 return; // Could be NULL in some tests.
198 std::vector<int> new_routing_ids;
199 dispatcher_host_->message_port_message_filter()->
200 UpdateMessagePortsWithNewRoutes(sent_message_port_ids,
201 &new_routing_ids);
203 dispatcher_host_->Send(
204 new ServiceWorkerMsg_MessageToDocument(
205 kDocumentMainThreadId, provider_id(),
206 message,
207 sent_message_port_ids,
208 new_routing_ids));
211 void ServiceWorkerProviderHost::AddScopedProcessReferenceToPattern(
212 const GURL& pattern) {
213 associated_patterns_.push_back(pattern);
214 IncreaseProcessReference(pattern);
217 ServiceWorkerObjectInfo ServiceWorkerProviderHost::CreateHandleAndPass(
218 ServiceWorkerVersion* version) {
219 ServiceWorkerObjectInfo info;
220 if (context_ && version) {
221 scoped_ptr<ServiceWorkerHandle> handle =
222 ServiceWorkerHandle::Create(context_,
223 dispatcher_host_,
224 kDocumentMainThreadId,
225 provider_id_,
226 version);
227 info = handle->GetObjectInfo();
228 dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
230 return info;
233 void ServiceWorkerProviderHost::IncreaseProcessReference(
234 const GURL& pattern) {
235 if (context_ && context_->process_manager()) {
236 context_->process_manager()->AddProcessReferenceToPattern(
237 pattern, process_id_);
241 void ServiceWorkerProviderHost::DecreaseProcessReference(
242 const GURL& pattern) {
243 if (context_ && context_->process_manager()) {
244 context_->process_manager()->RemoveProcessReferenceFromPattern(
245 pattern, process_id_);
249 bool ServiceWorkerProviderHost::IsContextAlive() {
250 return context_ != NULL;
253 } // namespace content