blob: 6572f6da70cf6fe65b34628bb887eeeba2989cec [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 "modules/serviceworkers/ServiceWorkerRegistration.h"
#include "bindings/core/v8/CallbackPromiseAdapter.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptState.h"
#include "core/dom/DOMException.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/ExecutionContext.h"
#include "core/events/Event.h"
#include "modules/EventTargetModules.h"
#include "modules/serviceworkers/ServiceWorkerContainerClient.h"
#include "modules/serviceworkers/ServiceWorkerError.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
namespace blink {
const AtomicString& ServiceWorkerRegistration::interfaceName() const
{
return EventTargetNames::ServiceWorkerRegistration;
}
void ServiceWorkerRegistration::dispatchUpdateFoundEvent()
{
dispatchEvent(Event::create(EventTypeNames::updatefound));
}
void ServiceWorkerRegistration::setInstalling(std::unique_ptr<WebServiceWorker::Handle> handle)
{
if (!getExecutionContext())
return;
m_installing = ServiceWorker::from(getExecutionContext(), adoptPtr(handle.release()));
}
void ServiceWorkerRegistration::setWaiting(std::unique_ptr<WebServiceWorker::Handle> handle)
{
if (!getExecutionContext())
return;
m_waiting = ServiceWorker::from(getExecutionContext(), adoptPtr(handle.release()));
}
void ServiceWorkerRegistration::setActive(std::unique_ptr<WebServiceWorker::Handle> handle)
{
if (!getExecutionContext())
return;
m_active = ServiceWorker::from(getExecutionContext(), adoptPtr(handle.release()));
}
ServiceWorkerRegistration* ServiceWorkerRegistration::getOrCreate(ExecutionContext* executionContext, PassOwnPtr<WebServiceWorkerRegistration::Handle> handle)
{
ASSERT(handle);
ServiceWorkerRegistration* existingRegistration = static_cast<ServiceWorkerRegistration*>(handle->registration()->proxy());
if (existingRegistration) {
ASSERT(existingRegistration->getExecutionContext() == executionContext);
return existingRegistration;
}
ServiceWorkerRegistration* newRegistration = new ServiceWorkerRegistration(executionContext, std::move(handle));
newRegistration->suspendIfNeeded();
return newRegistration;
}
String ServiceWorkerRegistration::scope() const
{
return m_handle->registration()->scope().string();
}
ScriptPromise ServiceWorkerRegistration::update(ScriptState* scriptState)
{
ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(getExecutionContext());
if (!client || !client->provider())
return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Failed to update a ServiceWorkerRegistration: No associated provider is available."));
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
m_handle->registration()->update(client->provider(), new CallbackPromiseAdapter<void, ServiceWorkerError>(resolver));
return promise;
}
ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* scriptState)
{
ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(getExecutionContext());
if (!client || !client->provider())
return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "Failed to unregister a ServiceWorkerRegistration: No associated provider is available."));
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
m_handle->registration()->unregister(client->provider(), new CallbackPromiseAdapter<bool, ServiceWorkerError>(resolver));
return promise;
}
ServiceWorkerRegistration::ServiceWorkerRegistration(ExecutionContext* executionContext, PassOwnPtr<WebServiceWorkerRegistration::Handle> handle)
: ActiveScriptWrappable(this)
, ActiveDOMObject(executionContext)
, m_handle(std::move(handle))
, m_stopped(false)
{
ASSERT(m_handle);
ASSERT(!m_handle->registration()->proxy());
ThreadState::current()->registerPreFinalizer(this);
if (!executionContext)
return;
m_handle->registration()->setProxy(this);
}
ServiceWorkerRegistration::~ServiceWorkerRegistration()
{
}
void ServiceWorkerRegistration::dispose()
{
// Promptly clears a raw reference from content/ to an on-heap object
// so that content/ doesn't access it in a lazy sweeping phase.
m_handle.reset();
}
DEFINE_TRACE(ServiceWorkerRegistration)
{
visitor->trace(m_installing);
visitor->trace(m_waiting);
visitor->trace(m_active);
EventTargetWithInlineData::trace(visitor);
ActiveDOMObject::trace(visitor);
Supplementable<ServiceWorkerRegistration>::trace(visitor);
}
bool ServiceWorkerRegistration::hasPendingActivity() const
{
return !m_stopped;
}
void ServiceWorkerRegistration::stop()
{
if (m_stopped)
return;
m_stopped = true;
m_handle->registration()->proxyStopped();
}
} // namespace blink