service_worker_provider_host.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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_provider_host.h" 6 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 20namespace content { 21 22static const int kDocumentMainThreadId = 0; 23 24ServiceWorkerProviderHost::ServiceWorkerProviderHost( 25 int process_id, int provider_id, 26 base::WeakPtr<ServiceWorkerContextCore> context, 27 ServiceWorkerDispatcherHost* dispatcher_host) 28 : process_id_(process_id), 29 provider_id_(provider_id), 30 context_(context), 31 dispatcher_host_(dispatcher_host) { 32} 33 34ServiceWorkerProviderHost::~ServiceWorkerProviderHost() { 35 // Clear docurl so the deferred activation of a waiting worker 36 // won't associate the new version with a provider being destroyed. 37 document_url_ = GURL(); 38 if (controlling_version_) 39 controlling_version_->RemoveControllee(this); 40 if (active_version_) 41 active_version_->RemovePotentialControllee(this); 42 if (waiting_version_) 43 waiting_version_->RemovePotentialControllee(this); 44 if (installing_version_) 45 installing_version_->RemovePotentialControllee(this); 46 if (associated_registration_) 47 associated_registration_->RemoveListener(this); 48} 49 50void ServiceWorkerProviderHost::OnVersionAttributesChanged( 51 ServiceWorkerRegistration* registration, 52 ChangedVersionAttributesMask changed_mask, 53 const ServiceWorkerRegistrationInfo& info) { 54 DCHECK_EQ(associated_registration_, registration); 55 SetVersionAttributes(registration->installing_version(), 56 registration->waiting_version(), 57 registration->active_version()); 58} 59 60void ServiceWorkerProviderHost::OnRegistrationFailed( 61 ServiceWorkerRegistration* registration) { 62 DCHECK_EQ(associated_registration_, registration); 63 UnassociateRegistration(); 64} 65 66void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) { 67 DCHECK(!url.has_ref()); 68 document_url_ = url; 69} 70 71void ServiceWorkerProviderHost::SetVersionAttributes( 72 ServiceWorkerVersion* installing_version, 73 ServiceWorkerVersion* waiting_version, 74 ServiceWorkerVersion* active_version) { 75 ChangedVersionAttributesMask mask; 76 77 if (installing_version != installing_version_) { 78 SetVersionAttributesInternal(installing_version, &installing_version_); 79 mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION); 80 } 81 if (waiting_version != waiting_version_) { 82 SetVersionAttributesInternal(waiting_version, &waiting_version_); 83 mask.add(ChangedVersionAttributesMask::WAITING_VERSION); 84 } 85 if (active_version != active_version_) { 86 SetVersionAttributesInternal(active_version, &active_version_); 87 mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION); 88 } 89 90 if (!dispatcher_host_) 91 return; // Could be NULL in some tests. 92 if (!mask.changed()) 93 return; 94 95 ServiceWorkerVersionAttributes attributes; 96 if (mask.installing_changed()) 97 attributes.installing = CreateHandleAndPass(installing_version); 98 if (mask.waiting_changed()) 99 attributes.waiting = CreateHandleAndPass(waiting_version); 100 if (mask.active_changed()) 101 attributes.active = CreateHandleAndPass(active_version); 102 103 dispatcher_host_->Send(new ServiceWorkerMsg_SetVersionAttributes( 104 kDocumentMainThreadId, 105 provider_id(), 106 kInvalidServiceWorkerRegistrationHandleId, 107 mask.changed(), 108 attributes)); 109} 110 111void ServiceWorkerProviderHost::SetVersionAttributesInternal( 112 ServiceWorkerVersion* version, 113 scoped_refptr<ServiceWorkerVersion>* data_member) { 114 scoped_refptr<ServiceWorkerVersion> previous_version = *data_member; 115 *data_member = version; 116 if (version) 117 version->AddPotentialControllee(this); 118 if (previous_version) 119 previous_version->RemovePotentialControllee(this); 120} 121 122void ServiceWorkerProviderHost::SetControllerVersionAttribute( 123 ServiceWorkerVersion* version) { 124 if (version == controlling_version_) 125 return; 126 127 scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_; 128 controlling_version_ = version; 129 if (version) 130 version->AddControllee(this); 131 if (previous_version) 132 previous_version->RemoveControllee(this); 133 134 if (!dispatcher_host_) 135 return; // Could be NULL in some tests. 136 137 dispatcher_host_->Send(new ServiceWorkerMsg_SetControllerServiceWorker( 138 kDocumentMainThreadId, provider_id(), CreateHandleAndPass(version))); 139} 140 141void ServiceWorkerProviderHost::ClearVersionAttributes() { 142 SetVersionAttributes(NULL, NULL, NULL); 143 SetControllerVersionAttribute(NULL); 144} 145 146bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) { 147 if (!context_) 148 return true; // System is shutting down. 149 if (active_version_) 150 return false; // Unexpected bad message. 151 152 ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id); 153 if (!live_version) 154 return true; // Was deleted before it got started. 155 156 ServiceWorkerVersionInfo info = live_version->GetInfo(); 157 if (info.running_status != ServiceWorkerVersion::STARTING || 158 info.process_id != process_id_) { 159 // If we aren't trying to start this version in our process 160 // something is amiss. 161 return false; 162 } 163 164 running_hosted_version_ = live_version; 165 return true; 166} 167 168void ServiceWorkerProviderHost::AssociateRegistration( 169 ServiceWorkerRegistration* registration) { 170 DCHECK(CanAssociateRegistration(registration)); 171 associated_registration_ = registration; 172 registration->AddListener(this); 173 SetVersionAttributes(registration->installing_version(), 174 registration->waiting_version(), 175 registration->active_version()); 176 SetControllerVersionAttribute(registration->active_version()); 177} 178 179void ServiceWorkerProviderHost::UnassociateRegistration() { 180 if (!associated_registration_) 181 return; 182 associated_registration_->RemoveListener(this); 183 associated_registration_ = NULL; 184 ClearVersionAttributes(); 185} 186 187scoped_ptr<ServiceWorkerRequestHandler> 188ServiceWorkerProviderHost::CreateRequestHandler( 189 ResourceType resource_type, 190 base::WeakPtr<storage::BlobStorageContext> blob_storage_context, 191 scoped_refptr<ResourceRequestBody> body) { 192 if (IsHostToRunningServiceWorker()) { 193 return scoped_ptr<ServiceWorkerRequestHandler>( 194 new ServiceWorkerContextRequestHandler( 195 context_, AsWeakPtr(), blob_storage_context, resource_type)); 196 } 197 if (ServiceWorkerUtils::IsMainResourceType(resource_type) || 198 active_version()) { 199 return scoped_ptr<ServiceWorkerRequestHandler>( 200 new ServiceWorkerControlleeRequestHandler( 201 context_, AsWeakPtr(), blob_storage_context, resource_type, body)); 202 } 203 return scoped_ptr<ServiceWorkerRequestHandler>(); 204} 205 206bool ServiceWorkerProviderHost::CanAssociateRegistration( 207 ServiceWorkerRegistration* registration) { 208 if (!context_) 209 return false; 210 if (running_hosted_version_) 211 return false; 212 if (!registration || associated_registration_) 213 return false; 214 return true; 215} 216 217void ServiceWorkerProviderHost::PostMessage( 218 const base::string16& message, 219 const std::vector<int>& sent_message_port_ids) { 220 if (!dispatcher_host_) 221 return; // Could be NULL in some tests. 222 223 std::vector<int> new_routing_ids; 224 dispatcher_host_->message_port_message_filter()-> 225 UpdateMessagePortsWithNewRoutes(sent_message_port_ids, 226 &new_routing_ids); 227 228 dispatcher_host_->Send( 229 new ServiceWorkerMsg_MessageToDocument( 230 kDocumentMainThreadId, provider_id(), 231 message, 232 sent_message_port_ids, 233 new_routing_ids)); 234} 235 236ServiceWorkerObjectInfo ServiceWorkerProviderHost::CreateHandleAndPass( 237 ServiceWorkerVersion* version) { 238 ServiceWorkerObjectInfo info; 239 if (context_ && version) { 240 scoped_ptr<ServiceWorkerHandle> handle = 241 ServiceWorkerHandle::Create(context_, 242 dispatcher_host_, 243 kDocumentMainThreadId, 244 provider_id_, 245 version); 246 info = handle->GetObjectInfo(); 247 dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass()); 248 } 249 return info; 250} 251 252bool ServiceWorkerProviderHost::IsContextAlive() { 253 return context_ != NULL; 254} 255 256} // namespace content 257