1 // Copyright 2014 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.
6 #include "ServiceWorkerRegistration.h"
8 #include "bindings/core/v8/CallbackPromiseAdapter.h"
9 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h"
11 #include "bindings/core/v8/ScriptState.h"
12 #include "core/dom/DOMException.h"
13 #include "core/dom/ExceptionCode.h"
14 #include "core/dom/ExecutionContext.h"
15 #include "core/events/Event.h"
16 #include "modules/EventTargetModules.h"
17 #include "modules/serviceworkers/ServiceWorkerContainerClient.h"
18 #include "modules/serviceworkers/ServiceWorkerError.h"
19 #include "public/platform/WebServiceWorkerProvider.h"
23 class UndefinedValue {
25 typedef WebServiceWorkerRegistration WebType;
26 static V8UndefinedType take(ScriptPromiseResolver* resolver, WebType* registration)
28 ASSERT(!registration); // Anything passed here will be leaked.
29 return V8UndefinedType();
31 static void dispose(WebType* registration)
33 ASSERT(!registration); // Anything passed here will be leaked.
40 static void deleteIfNoExistingOwner(WebServiceWorker* serviceWorker)
42 if (serviceWorker && !serviceWorker->proxy())
46 const AtomicString& ServiceWorkerRegistration::interfaceName() const
48 return EventTargetNames::ServiceWorkerRegistration;
51 void ServiceWorkerRegistration::dispatchUpdateFoundEvent()
53 dispatchEvent(Event::create(EventTypeNames::updatefound));
56 void ServiceWorkerRegistration::setInstalling(WebServiceWorker* serviceWorker)
58 if (!executionContext()) {
59 deleteIfNoExistingOwner(serviceWorker);
62 m_installing = ServiceWorker::from(executionContext(), serviceWorker);
65 void ServiceWorkerRegistration::setWaiting(WebServiceWorker* serviceWorker)
67 if (!executionContext()) {
68 deleteIfNoExistingOwner(serviceWorker);
71 m_waiting = ServiceWorker::from(executionContext(), serviceWorker);
74 void ServiceWorkerRegistration::setActive(WebServiceWorker* serviceWorker)
76 if (!executionContext()) {
77 deleteIfNoExistingOwner(serviceWorker);
80 m_active = ServiceWorker::from(executionContext(), serviceWorker);
83 PassRefPtrWillBeRawPtr<ServiceWorkerRegistration> ServiceWorkerRegistration::take(ScriptPromiseResolver* resolver, WebType* registration)
87 return getOrCreate(resolver->scriptState()->executionContext(), registration);
90 void ServiceWorkerRegistration::dispose(WebType* registration)
95 String ServiceWorkerRegistration::scope() const
97 return m_outerRegistration->scope().string();
100 ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* scriptState)
102 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
103 ScriptPromise promise = resolver->promise();
106 resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available"));
110 RefPtr<SecurityOrigin> documentOrigin = scriptState->executionContext()->securityOrigin();
111 KURL scopeURL = scriptState->executionContext()->completeURL(scope());
112 scopeURL.removeFragmentIdentifier();
113 if (!scope().isEmpty() && !documentOrigin->canRequest(scopeURL)) {
114 resolver->reject(DOMException::create(SecurityError, "Can only unregister for scopes in the document's origin."));
118 m_provider->unregisterServiceWorker(scopeURL, new CallbackPromiseAdapter<UndefinedValue, ServiceWorkerError>(resolver));
122 PassRefPtrWillBeRawPtr<ServiceWorkerRegistration> ServiceWorkerRegistration::getOrCreate(ExecutionContext* executionContext, WebServiceWorkerRegistration* outerRegistration)
124 if (!outerRegistration)
127 WebServiceWorkerRegistrationProxy* proxy = outerRegistration->proxy();
129 ServiceWorkerRegistration* existingRegistration = *proxy;
130 if (existingRegistration) {
131 ASSERT(existingRegistration->executionContext() == executionContext);
132 return existingRegistration;
136 RefPtrWillBeRawPtr<ServiceWorkerRegistration> registration = adoptRefWillBeRefCountedGarbageCollected(new ServiceWorkerRegistration(executionContext, adoptPtr(outerRegistration)));
137 registration->suspendIfNeeded();
138 return registration.release();
141 ServiceWorkerRegistration::ServiceWorkerRegistration(ExecutionContext* executionContext, PassOwnPtr<WebServiceWorkerRegistration> outerRegistration)
142 : ActiveDOMObject(executionContext)
143 , WebServiceWorkerRegistrationProxy(this)
144 , m_outerRegistration(outerRegistration)
148 ASSERT(m_outerRegistration);
149 ScriptWrappable::init(this);
151 if (!executionContext)
153 if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext))
154 m_provider = client->provider();
155 m_outerRegistration->setProxy(this);
158 void ServiceWorkerRegistration::trace(Visitor* visitor)
160 visitor->trace(m_installing);
161 visitor->trace(m_waiting);
162 visitor->trace(m_active);
163 EventTargetWithInlineData::trace(visitor);
166 bool ServiceWorkerRegistration::hasPendingActivity() const
171 void ServiceWorkerRegistration::stop()
176 m_outerRegistration->proxyStopped();