blob: debeb893eff2982b1740700544a549a866c4e69a [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include <utility>
#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/child_process_host.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
namespace content {
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
int render_process_id)
: render_process_id_(render_process_id), context_wrapper_(context_wrapper) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
void ServiceWorkerDispatcherHost::AddBinding(
blink::mojom::ServiceWorkerDispatcherHostAssociatedRequest request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
bindings_.AddBinding(this, std::move(request));
}
void ServiceWorkerDispatcherHost::RenderProcessExited(
RenderProcessHost* host,
const ChildProcessTerminationInfo& info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// TODO(crbug.com/736203) Try to remove this call. It should be unnecessary
// because provider hosts remove themselves when their Mojo connection to the
// renderer is destroyed. But if we don't remove the hosts immediately here,
// collisions of <process_id, provider_id> can occur if |this| is reused for
// another new renderer process due to reuse of the RenderProcessHost.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerDispatcherHost::RemoveAllProviderHostsForProcess,
base::Unretained(this)));
}
void ServiceWorkerDispatcherHost::OnProviderCreated(
blink::mojom::ServiceWorkerProviderHostInfoPtr info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnProviderCreated");
ServiceWorkerContextCore* context = context_wrapper_->context();
if (!context)
return;
// Provider hosts for navigations are precreated on the browser process with a
// browser-assigned id. The renderer process calls OnProviderCreated once it
// creates the provider.
if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info->provider_id)) {
if (info->type != blink::mojom::ServiceWorkerProviderType::kForWindow) {
bindings_.ReportBadMessage(
"SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW");
return;
}
// Retrieve the provider host pre-created for the navigation.
ServiceWorkerProviderHost* provider_host = context->GetProviderHost(
ChildProcessHost::kInvalidUniqueID, info->provider_id);
// If no host is found, create one.
// TODO(crbug.com/789111#c14): This is probably not right, see bug.
if (!provider_host) {
context->AddProviderHost(ServiceWorkerProviderHost::Create(
render_process_id_, std::move(info), context->AsWeakPtr()));
return;
}
// Otherwise, complete initialization of the pre-created host.
if (provider_host->process_id() != ChildProcessHost::kInvalidUniqueID) {
bindings_.ReportBadMessage("SWDH_PRECREATED_PROVIDER_RESUED");
return;
}
provider_host->CompleteNavigationInitialized(render_process_id_,
std::move(info));
return;
}
// Provider hosts for service workers don't call OnProviderCreated. They are
// precreated and ServiceWorkerProviderHost::CompleteStartWorkerPreparation is
// called during the startup sequence once a process is allocated.
if (info->type ==
blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
bindings_.ReportBadMessage(
"SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER");
return;
}
if (context->GetProviderHost(render_process_id_, info->provider_id)) {
bindings_.ReportBadMessage("SWDH_PROVIDER_CREATED_DUPLICATE_ID");
return;
}
context->AddProviderHost(ServiceWorkerProviderHost::Create(
render_process_id_, std::move(info), context->AsWeakPtr()));
}
void ServiceWorkerDispatcherHost::RemoveAllProviderHostsForProcess() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (context_wrapper_->context()) {
context_wrapper_->context()->RemoveAllProviderHostsForProcess(
render_process_id_);
}
}
} // namespace content