blob: 136422d9d4054e0873d29bd4f3a253d30301e086 [file] [log] [blame]
// Copyright 2014 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/child/service_worker/service_worker_provider_context.h"
#include <utility>
#include "base/macros.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/child_thread_impl.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/worker_thread_registry.h"
namespace content {
class ServiceWorkerProviderContext::Delegate {
public:
virtual ~Delegate() {}
virtual void AssociateRegistration(
std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
std::unique_ptr<ServiceWorkerHandleReference> installing,
std::unique_ptr<ServiceWorkerHandleReference> waiting,
std::unique_ptr<ServiceWorkerHandleReference> active) = 0;
virtual void DisassociateRegistration() = 0;
virtual void GetAssociatedRegistration(
ServiceWorkerRegistrationObjectInfo* info,
ServiceWorkerVersionAttributes* attrs) = 0;
virtual bool HasAssociatedRegistration() = 0;
virtual void SetController(
std::unique_ptr<ServiceWorkerHandleReference> controller) = 0;
virtual ServiceWorkerHandleReference* controller() = 0;
};
// Delegate class for ServiceWorker client (Document, SharedWorker, etc) to
// keep the associated registration and the controller until
// ServiceWorkerContainer is initialized.
class ServiceWorkerProviderContext::ControlleeDelegate
: public ServiceWorkerProviderContext::Delegate {
public:
ControlleeDelegate() {}
~ControlleeDelegate() override {}
void AssociateRegistration(
std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
std::unique_ptr<ServiceWorkerHandleReference> /* installing */,
std::unique_ptr<ServiceWorkerHandleReference> /* waiting */,
std::unique_ptr<ServiceWorkerHandleReference> /* active */) override {
DCHECK(!registration_);
registration_ = std::move(registration);
}
void DisassociateRegistration() override {
controller_.reset();
registration_.reset();
}
void SetController(
std::unique_ptr<ServiceWorkerHandleReference> controller) override {
DCHECK(registration_);
DCHECK(!controller ||
controller->handle_id() != kInvalidServiceWorkerHandleId);
controller_ = std::move(controller);
}
bool HasAssociatedRegistration() override { return !!registration_; }
void GetAssociatedRegistration(
ServiceWorkerRegistrationObjectInfo* /* info */,
ServiceWorkerVersionAttributes* /* attrs */) override {
NOTREACHED();
}
ServiceWorkerHandleReference* controller() override {
return controller_.get();
}
private:
std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration_;
std::unique_ptr<ServiceWorkerHandleReference> controller_;
DISALLOW_COPY_AND_ASSIGN(ControlleeDelegate);
};
// Delegate class for ServiceWorkerGlobalScope to keep the associated
// registration and its versions until the execution context is initialized.
class ServiceWorkerProviderContext::ControllerDelegate
: public ServiceWorkerProviderContext::Delegate {
public:
ControllerDelegate() {}
~ControllerDelegate() override {}
void AssociateRegistration(
std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
std::unique_ptr<ServiceWorkerHandleReference> installing,
std::unique_ptr<ServiceWorkerHandleReference> waiting,
std::unique_ptr<ServiceWorkerHandleReference> active) override {
DCHECK(!registration_);
registration_ = std::move(registration);
installing_ = std::move(installing);
waiting_ = std::move(waiting);
active_ = std::move(active);
}
void DisassociateRegistration() override {
// ServiceWorkerGlobalScope is never disassociated.
NOTREACHED();
}
void SetController(
std::unique_ptr<ServiceWorkerHandleReference> /* controller */) override {
NOTREACHED();
}
bool HasAssociatedRegistration() override { return !!registration_; }
void GetAssociatedRegistration(
ServiceWorkerRegistrationObjectInfo* info,
ServiceWorkerVersionAttributes* attrs) override {
DCHECK(HasAssociatedRegistration());
*info = registration_->info();
if (installing_)
attrs->installing = installing_->info();
if (waiting_)
attrs->waiting = waiting_->info();
if (active_)
attrs->active = active_->info();
}
ServiceWorkerHandleReference* controller() override {
NOTREACHED();
return nullptr;
}
private:
std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration_;
std::unique_ptr<ServiceWorkerHandleReference> installing_;
std::unique_ptr<ServiceWorkerHandleReference> waiting_;
std::unique_ptr<ServiceWorkerHandleReference> active_;
DISALLOW_COPY_AND_ASSIGN(ControllerDelegate);
};
ServiceWorkerProviderContext::ServiceWorkerProviderContext(
int provider_id,
ServiceWorkerProviderType provider_type,
mojom::ServiceWorkerProviderAssociatedRequest request,
ThreadSafeSender* thread_safe_sender)
: provider_id_(provider_id),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
thread_safe_sender_(thread_safe_sender),
binding_(this, std::move(request)) {
if (provider_type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER)
delegate_.reset(new ControllerDelegate);
else
delegate_.reset(new ControlleeDelegate);
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
thread_safe_sender_.get(), main_thread_task_runner_.get());
dispatcher->AddProviderContext(this);
}
ServiceWorkerProviderContext::~ServiceWorkerProviderContext() {
if (ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance()) {
// Remove this context from the dispatcher living on the main thread.
dispatcher->RemoveProviderContext(this);
}
}
void ServiceWorkerProviderContext::OnAssociateRegistration(
std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
std::unique_ptr<ServiceWorkerHandleReference> installing,
std::unique_ptr<ServiceWorkerHandleReference> waiting,
std::unique_ptr<ServiceWorkerHandleReference> active) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
delegate_->AssociateRegistration(std::move(registration),
std::move(installing), std::move(waiting),
std::move(active));
}
void ServiceWorkerProviderContext::OnDisassociateRegistration() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
delegate_->DisassociateRegistration();
}
void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
std::unique_ptr<ServiceWorkerHandleReference> controller,
const std::set<uint32_t>& used_features) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
delegate_->SetController(std::move(controller));
used_features_ = used_features;
}
void ServiceWorkerProviderContext::GetAssociatedRegistration(
ServiceWorkerRegistrationObjectInfo* info,
ServiceWorkerVersionAttributes* attrs) {
DCHECK(!main_thread_task_runner_->RunsTasksInCurrentSequence());
delegate_->GetAssociatedRegistration(info, attrs);
}
bool ServiceWorkerProviderContext::HasAssociatedRegistration() {
return delegate_->HasAssociatedRegistration();
}
ServiceWorkerHandleReference* ServiceWorkerProviderContext::controller() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
return delegate_->controller();
}
void ServiceWorkerProviderContext::CountFeature(uint32_t feature) {
// ServiceWorkerProviderContext keeps track of features in order to propagate
// it to WebServiceWorkerProviderClient, which actually records the
// UseCounter.
used_features_.insert(feature);
}
void ServiceWorkerProviderContext::DestructOnMainThread() const {
if (!main_thread_task_runner_->RunsTasksInCurrentSequence() &&
main_thread_task_runner_->DeleteSoon(FROM_HERE, this)) {
return;
}
delete this;
}
} // namespace content