Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / serviceworkers / ServiceWorkerRegistration.cpp
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.
4
5 #include "config.h"
6 #include "ServiceWorkerRegistration.h"
7
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"
20
21 namespace blink {
22
23 class UndefinedValue {
24 public:
25     typedef WebServiceWorkerRegistration WebType;
26     static V8UndefinedType take(ScriptPromiseResolver* resolver, WebType* registration)
27     {
28         ASSERT(!registration); // Anything passed here will be leaked.
29         return V8UndefinedType();
30     }
31     static void dispose(WebType* registration)
32     {
33         ASSERT(!registration); // Anything passed here will be leaked.
34     }
35
36 private:
37     UndefinedValue();
38 };
39
40 static void deleteIfNoExistingOwner(WebServiceWorker* serviceWorker)
41 {
42     if (serviceWorker && !serviceWorker->proxy())
43         delete serviceWorker;
44 }
45
46 const AtomicString& ServiceWorkerRegistration::interfaceName() const
47 {
48     return EventTargetNames::ServiceWorkerRegistration;
49 }
50
51 void ServiceWorkerRegistration::dispatchUpdateFoundEvent()
52 {
53     dispatchEvent(Event::create(EventTypeNames::updatefound));
54 }
55
56 void ServiceWorkerRegistration::setInstalling(WebServiceWorker* serviceWorker)
57 {
58     if (!executionContext()) {
59         deleteIfNoExistingOwner(serviceWorker);
60         return;
61     }
62     m_installing = ServiceWorker::from(executionContext(), serviceWorker);
63 }
64
65 void ServiceWorkerRegistration::setWaiting(WebServiceWorker* serviceWorker)
66 {
67     if (!executionContext()) {
68         deleteIfNoExistingOwner(serviceWorker);
69         return;
70     }
71     m_waiting = ServiceWorker::from(executionContext(), serviceWorker);
72 }
73
74 void ServiceWorkerRegistration::setActive(WebServiceWorker* serviceWorker)
75 {
76     if (!executionContext()) {
77         deleteIfNoExistingOwner(serviceWorker);
78         return;
79     }
80     m_active = ServiceWorker::from(executionContext(), serviceWorker);
81 }
82
83 PassRefPtrWillBeRawPtr<ServiceWorkerRegistration> ServiceWorkerRegistration::take(ScriptPromiseResolver* resolver, WebType* registration)
84 {
85     if (!registration)
86         return nullptr;
87     return getOrCreate(resolver->scriptState()->executionContext(), registration);
88 }
89
90 void ServiceWorkerRegistration::dispose(WebType* registration)
91 {
92     delete registration;
93 }
94
95 String ServiceWorkerRegistration::scope() const
96 {
97     return m_outerRegistration->scope().string();
98 }
99
100 ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* scriptState)
101 {
102     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
103     ScriptPromise promise = resolver->promise();
104
105     if (!m_provider) {
106         resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available"));
107         return promise;
108     }
109
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."));
115         return promise;
116     }
117
118     m_provider->unregisterServiceWorker(scopeURL, new CallbackPromiseAdapter<UndefinedValue, ServiceWorkerError>(resolver));
119     return promise;
120 }
121
122 PassRefPtrWillBeRawPtr<ServiceWorkerRegistration> ServiceWorkerRegistration::getOrCreate(ExecutionContext* executionContext, WebServiceWorkerRegistration* outerRegistration)
123 {
124     if (!outerRegistration)
125         return nullptr;
126
127     WebServiceWorkerRegistrationProxy* proxy = outerRegistration->proxy();
128     if (proxy) {
129         ServiceWorkerRegistration* existingRegistration = *proxy;
130         if (existingRegistration) {
131             ASSERT(existingRegistration->executionContext() == executionContext);
132             return existingRegistration;
133         }
134     }
135
136     RefPtrWillBeRawPtr<ServiceWorkerRegistration> registration = adoptRefWillBeRefCountedGarbageCollected(new ServiceWorkerRegistration(executionContext, adoptPtr(outerRegistration)));
137     registration->suspendIfNeeded();
138     return registration.release();
139 }
140
141 ServiceWorkerRegistration::ServiceWorkerRegistration(ExecutionContext* executionContext, PassOwnPtr<WebServiceWorkerRegistration> outerRegistration)
142     : ActiveDOMObject(executionContext)
143     , WebServiceWorkerRegistrationProxy(this)
144     , m_outerRegistration(outerRegistration)
145     , m_provider(0)
146     , m_stopped(false)
147 {
148     ASSERT(m_outerRegistration);
149     ScriptWrappable::init(this);
150
151     if (!executionContext)
152         return;
153     if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext))
154         m_provider = client->provider();
155     m_outerRegistration->setProxy(this);
156 }
157
158 void ServiceWorkerRegistration::trace(Visitor* visitor)
159 {
160     visitor->trace(m_installing);
161     visitor->trace(m_waiting);
162     visitor->trace(m_active);
163     EventTargetWithInlineData::trace(visitor);
164 }
165
166 bool ServiceWorkerRegistration::hasPendingActivity() const
167 {
168     return !m_stopped;
169 }
170
171 void ServiceWorkerRegistration::stop()
172 {
173     if (m_stopped)
174         return;
175     m_stopped = true;
176     m_outerRegistration->proxyStopped();
177 }
178
179 } // namespace blink