1c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)// found in the LICENSE file.
4c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
5c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "config.h"
6c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "ServiceWorkerRegistration.h"
7c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
8c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/CallbackPromiseAdapter.h"
9c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/ScriptPromise.h"
10c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/ScriptPromiseResolver.h"
11c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/ScriptState.h"
12c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/dom/DOMException.h"
13c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/dom/ExceptionCode.h"
14c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/dom/ExecutionContext.h"
15e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "core/events/Event.h"
16c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "modules/EventTargetModules.h"
17c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "modules/serviceworkers/ServiceWorkerContainerClient.h"
18c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "modules/serviceworkers/ServiceWorkerError.h"
19c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "public/platform/WebServiceWorkerProvider.h"
20c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
21c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
22c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass BooleanValue {
24c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public:
257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    typedef bool WebType;
267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static bool take(ScriptPromiseResolver* resolver, WebType* boolean)
27c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return *boolean;
29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static void dispose(WebType* boolean) { }
31c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
32c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private:
337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    BooleanValue();
34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)};
35c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
36e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)static void deleteIfNoExistingOwner(WebServiceWorker* serviceWorker)
37e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
38e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (serviceWorker && !serviceWorker->proxy())
39e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        delete serviceWorker;
40e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
41e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)const AtomicString& ServiceWorkerRegistration::interfaceName() const
43c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return EventTargetNames::ServiceWorkerRegistration;
45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
46c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
47e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::dispatchUpdateFoundEvent()
48e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
49e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    dispatchEvent(Event::create(EventTypeNames::updatefound));
50e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
51e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
52e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::setInstalling(WebServiceWorker* serviceWorker)
53e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
54e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (!executionContext()) {
55e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        deleteIfNoExistingOwner(serviceWorker);
56e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
57e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
58e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_installing = ServiceWorker::from(executionContext(), serviceWorker);
59e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
60e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
61e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::setWaiting(WebServiceWorker* serviceWorker)
62e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
63e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (!executionContext()) {
64e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        deleteIfNoExistingOwner(serviceWorker);
65e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
66e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
67e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_waiting = ServiceWorker::from(executionContext(), serviceWorker);
68e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
69e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
70e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::setActive(WebServiceWorker* serviceWorker)
71e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
72e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (!executionContext()) {
73e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        deleteIfNoExistingOwner(serviceWorker);
74e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
75e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
76e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_active = ServiceWorker::from(executionContext(), serviceWorker);
77e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
78e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciServiceWorkerRegistration* ServiceWorkerRegistration::from(ExecutionContext* executionContext, WebType* registration)
80c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
81c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!registration)
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return 0;
837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return getOrCreate(executionContext, registration);
847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciServiceWorkerRegistration* ServiceWorkerRegistration::take(ScriptPromiseResolver* resolver, WebType* registration)
877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return from(resolver->scriptState()->executionContext(), registration);
89e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
90e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
91e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::dispose(WebType* registration)
92e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
93e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    delete registration;
94c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
95c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
96c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)String ServiceWorkerRegistration::scope() const
97c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
98c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_outerRegistration->scope().string();
99c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
100c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
101c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* scriptState)
102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
103c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ScriptPromise promise = resolver->promise();
105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!m_provider) {
107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available"));
108c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return promise;
109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RefPtr<SecurityOrigin> documentOrigin = scriptState->executionContext()->securityOrigin();
112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    KURL scopeURL = scriptState->executionContext()->completeURL(scope());
113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    scopeURL.removeFragmentIdentifier();
114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!scope().isEmpty() && !documentOrigin->canRequest(scopeURL)) {
115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        resolver->reject(DOMException::create(SecurityError, "Can only unregister for scopes in the document's origin."));
116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return promise;
117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_provider->unregisterServiceWorker(scopeURL, new CallbackPromiseAdapter<BooleanValue, ServiceWorkerError>(resolver));
120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return promise;
121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciServiceWorkerRegistration* ServiceWorkerRegistration::getOrCreate(ExecutionContext* executionContext, WebServiceWorkerRegistration* outerRegistration)
124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
125e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (!outerRegistration)
1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return 0;
127e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
128e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    WebServiceWorkerRegistrationProxy* proxy = outerRegistration->proxy();
129e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (proxy) {
130e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        ServiceWorkerRegistration* existingRegistration = *proxy;
131e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        if (existingRegistration) {
132e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            ASSERT(existingRegistration->executionContext() == executionContext);
133e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            return existingRegistration;
134e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        }
135e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
136e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ServiceWorkerRegistration* registration = adoptRefCountedGarbageCollectedWillBeNoop(new ServiceWorkerRegistration(executionContext, adoptPtr(outerRegistration)));
138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    registration->suspendIfNeeded();
1397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return registration;
140c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
142c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ServiceWorkerRegistration::ServiceWorkerRegistration(ExecutionContext* executionContext, PassOwnPtr<WebServiceWorkerRegistration> outerRegistration)
143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    : ActiveDOMObject(executionContext)
144e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    , WebServiceWorkerRegistrationProxy(this)
145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_outerRegistration(outerRegistration)
146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_provider(0)
147e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    , m_stopped(false)
148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_outerRegistration);
150c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
151c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!executionContext)
152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return;
153c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext))
154c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_provider = client->provider();
155e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_outerRegistration->setProxy(this);
156e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
157e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
158e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::trace(Visitor* visitor)
159e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
160e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    visitor->trace(m_installing);
161e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    visitor->trace(m_waiting);
162e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    visitor->trace(m_active);
163e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    EventTargetWithInlineData::trace(visitor);
164e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
165e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
166e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)bool ServiceWorkerRegistration::hasPendingActivity() const
167e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
168e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    return !m_stopped;
169e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
170e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
171e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ServiceWorkerRegistration::stop()
172e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
173e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (m_stopped)
174e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
175e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_stopped = true;
176e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_outerRegistration->proxyStopped();
177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
179c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
180