Update To 11.40.268.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 BooleanValue {
24 public:
25     typedef bool WebType;
26     static bool take(ScriptPromiseResolver* resolver, WebType* boolean)
27     {
28         return *boolean;
29     }
30     static void dispose(WebType* boolean) { }
31
32 private:
33     BooleanValue();
34 };
35
36 static void deleteIfNoExistingOwner(WebServiceWorker* serviceWorker)
37 {
38     if (serviceWorker && !serviceWorker->proxy())
39         delete serviceWorker;
40 }
41
42 const AtomicString& ServiceWorkerRegistration::interfaceName() const
43 {
44     return EventTargetNames::ServiceWorkerRegistration;
45 }
46
47 void ServiceWorkerRegistration::dispatchUpdateFoundEvent()
48 {
49     dispatchEvent(Event::create(EventTypeNames::updatefound));
50 }
51
52 void ServiceWorkerRegistration::setInstalling(WebServiceWorker* serviceWorker)
53 {
54     if (!executionContext()) {
55         deleteIfNoExistingOwner(serviceWorker);
56         return;
57     }
58     m_installing = ServiceWorker::from(executionContext(), serviceWorker);
59 }
60
61 void ServiceWorkerRegistration::setWaiting(WebServiceWorker* serviceWorker)
62 {
63     if (!executionContext()) {
64         deleteIfNoExistingOwner(serviceWorker);
65         return;
66     }
67     m_waiting = ServiceWorker::from(executionContext(), serviceWorker);
68 }
69
70 void ServiceWorkerRegistration::setActive(WebServiceWorker* serviceWorker)
71 {
72     if (!executionContext()) {
73         deleteIfNoExistingOwner(serviceWorker);
74         return;
75     }
76     m_active = ServiceWorker::from(executionContext(), serviceWorker);
77 }
78
79 ServiceWorkerRegistration* ServiceWorkerRegistration::from(ExecutionContext* executionContext, WebType* registration)
80 {
81     if (!registration)
82         return 0;
83     return getOrCreate(executionContext, registration);
84 }
85
86 ServiceWorkerRegistration* ServiceWorkerRegistration::take(ScriptPromiseResolver* resolver, WebType* registration)
87 {
88     return from(resolver->scriptState()->executionContext(), registration);
89 }
90
91 void ServiceWorkerRegistration::dispose(WebType* registration)
92 {
93     if (registration && !registration->proxy())
94         delete registration;
95 }
96
97 String ServiceWorkerRegistration::scope() const
98 {
99     return m_outerRegistration->scope().string();
100 }
101
102 ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* scriptState)
103 {
104     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
105     ScriptPromise promise = resolver->promise();
106
107     if (!m_provider) {
108         resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available"));
109         return promise;
110     }
111
112     RefPtr<SecurityOrigin> documentOrigin = scriptState->executionContext()->securityOrigin();
113     KURL scopeURL = scriptState->executionContext()->completeURL(scope());
114     scopeURL.removeFragmentIdentifier();
115     if (!scope().isEmpty() && !documentOrigin->canRequest(scopeURL)) {
116         resolver->reject(DOMException::create(SecurityError, "Can only unregister for scopes in the document's origin."));
117         return promise;
118     }
119
120     m_provider->unregisterServiceWorker(scopeURL, new CallbackPromiseAdapter<BooleanValue, ServiceWorkerError>(resolver));
121     return promise;
122 }
123
124 ServiceWorkerRegistration* ServiceWorkerRegistration::getOrCreate(ExecutionContext* executionContext, WebServiceWorkerRegistration* outerRegistration)
125 {
126     if (!outerRegistration)
127         return 0;
128
129     ServiceWorkerRegistration* existingRegistration = static_cast<ServiceWorkerRegistration*>(outerRegistration->proxy());
130     if (existingRegistration) {
131         ASSERT(existingRegistration->executionContext() == executionContext);
132         return existingRegistration;
133     }
134
135     ServiceWorkerRegistration* registration = new ServiceWorkerRegistration(executionContext, adoptPtr(outerRegistration));
136     registration->suspendIfNeeded();
137     return registration;
138 }
139
140 ServiceWorkerRegistration::ServiceWorkerRegistration(ExecutionContext* executionContext, PassOwnPtr<WebServiceWorkerRegistration> outerRegistration)
141     : ActiveDOMObject(executionContext)
142     , m_outerRegistration(outerRegistration)
143     , m_provider(0)
144     , m_stopped(false)
145 {
146     ASSERT(m_outerRegistration);
147
148     if (!executionContext)
149         return;
150     if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext))
151         m_provider = client->provider();
152     m_outerRegistration->setProxy(this);
153 }
154
155 void ServiceWorkerRegistration::trace(Visitor* visitor)
156 {
157     visitor->trace(m_installing);
158     visitor->trace(m_waiting);
159     visitor->trace(m_active);
160     EventTargetWithInlineData::trace(visitor);
161     HeapSupplementable<ServiceWorkerRegistration>::trace(visitor);
162 }
163
164 bool ServiceWorkerRegistration::hasPendingActivity() const
165 {
166     return !m_stopped;
167 }
168
169 void ServiceWorkerRegistration::stop()
170 {
171     if (m_stopped)
172         return;
173     m_stopped = true;
174     m_outerRegistration->proxyStopped();
175 }
176
177 } // namespace blink