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 "modules/serviceworkers/RespondWithObserver.h"
8 #include "bindings/core/v8/ScriptFunction.h"
9 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptValue.h"
11 #include "bindings/core/v8/V8Binding.h"
12 #include "bindings/modules/v8/V8Response.h"
13 #include "core/dom/ExecutionContext.h"
14 #include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
15 #include "platform/RuntimeEnabledFeatures.h"
16 #include "public/platform/WebServiceWorkerResponse.h"
17 #include "wtf/Assertions.h"
18 #include "wtf/RefPtr.h"
23 class RespondWithObserver::ThenFunction final : public ScriptFunction {
30 static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, RespondWithObserver* observer, ResolveType type)
32 ThenFunction* self = new ThenFunction(scriptState, observer, type);
33 return self->bindToV8Function();
36 virtual void trace(Visitor* visitor) override
38 visitor->trace(m_observer);
39 ScriptFunction::trace(visitor);
43 ThenFunction(ScriptState* scriptState, RespondWithObserver* observer, ResolveType type)
44 : ScriptFunction(scriptState)
45 , m_observer(observer)
50 virtual ScriptValue call(ScriptValue value) override
53 ASSERT(m_resolveType == Fulfilled || m_resolveType == Rejected);
54 if (m_resolveType == Rejected)
55 m_observer->responseWasRejected();
57 m_observer->responseWasFulfilled(value);
62 Member<RespondWithObserver> m_observer;
63 ResolveType m_resolveType;
66 RespondWithObserver* RespondWithObserver::create(ExecutionContext* context, int eventID, WebURLRequest::FetchRequestMode requestMode, WebURLRequest::FrameType frameType)
68 return new RespondWithObserver(context, eventID, requestMode, frameType);
71 void RespondWithObserver::contextDestroyed()
73 ContextLifecycleObserver::contextDestroyed();
77 void RespondWithObserver::didDispatchEvent()
79 ASSERT(executionContext());
80 if (m_state != Initial)
82 ServiceWorkerGlobalScopeClient::from(executionContext())->didHandleFetchEvent(m_eventID);
86 void RespondWithObserver::respondWith(ScriptState* scriptState, const ScriptValue& value, ExceptionState& exceptionState)
88 ASSERT(RuntimeEnabledFeatures::serviceWorkerOnFetchEnabled());
89 if (m_state != Initial) {
90 exceptionState.throwDOMException(InvalidStateError, "respondWith is already called.");
95 ScriptPromise::cast(scriptState, value).then(
96 ThenFunction::createFunction(scriptState, this, ThenFunction::Fulfilled),
97 ThenFunction::createFunction(scriptState, this, ThenFunction::Rejected));
100 void RespondWithObserver::responseWasRejected()
102 ASSERT(executionContext());
103 // The default value of WebServiceWorkerResponse's status is 0, which maps
104 // to a network error.
105 WebServiceWorkerResponse webResponse;
106 ServiceWorkerGlobalScopeClient::from(executionContext())->didHandleFetchEvent(m_eventID, webResponse);
110 void RespondWithObserver::responseWasFulfilled(const ScriptValue& value)
112 ASSERT(executionContext());
113 if (!V8Response::hasInstance(value.v8Value(), toIsolate(executionContext()))) {
114 responseWasRejected();
117 Response* response = V8Response::toImplWithTypeCheck(toIsolate(executionContext()), value.v8Value());
118 // "If either |response|'s type is |opaque| and |request|'s mode is not
119 // |no CORS| or |response|'s type is |error|, return a network error."
120 const FetchResponseData::Type responseType = response->response()->type();
121 if ((responseType == FetchResponseData::OpaqueType && m_requestMode != WebURLRequest::FetchRequestModeNoCORS) || responseType == FetchResponseData::ErrorType) {
122 responseWasRejected();
125 // Treat the opaque response as a network error for frame loading.
126 if (responseType == FetchResponseData::OpaqueType && m_frameType != WebURLRequest::FrameTypeNone) {
127 responseWasRejected();
130 WebServiceWorkerResponse webResponse;
131 response->populateWebServiceWorkerResponse(webResponse);
132 ServiceWorkerGlobalScopeClient::from(executionContext())->didHandleFetchEvent(m_eventID, webResponse);
136 RespondWithObserver::RespondWithObserver(ExecutionContext* context, int eventID, WebURLRequest::FetchRequestMode requestMode, WebURLRequest::FrameType frameType)
137 : ContextLifecycleObserver(context)
139 , m_requestMode(requestMode)
140 , m_frameType(frameType)