Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp

Issue 2715663002: ServiceWorker: Factor out FetchEvent related logics from RespondWithObserver. (Closed)
Patch Set: ServiceWorker: Factor out FetchEvent related logics from RespondWithObserver. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/serviceworkers/RespondWithObserver.h" 5 #include "modules/serviceworkers/FetchRespondWithObserver.h"
6 6
7 #include "bindings/core/v8/ScriptFunction.h" 7 #include <v8.h>
8 #include "bindings/core/v8/ScriptPromise.h"
9 #include "bindings/core/v8/ScriptValue.h" 8 #include "bindings/core/v8/ScriptValue.h"
10 #include "bindings/core/v8/V8Binding.h" 9 #include "bindings/core/v8/V8Binding.h"
11 #include "bindings/modules/v8/V8Response.h" 10 #include "bindings/modules/v8/V8Response.h"
12 #include "core/dom/ExceptionCode.h"
13 #include "core/dom/ExecutionContext.h" 11 #include "core/dom/ExecutionContext.h"
14 #include "core/inspector/ConsoleMessage.h" 12 #include "core/inspector/ConsoleMessage.h"
13 #include "core/inspector/ConsoleTypes.h"
15 #include "core/streams/Stream.h" 14 #include "core/streams/Stream.h"
16 #include "modules/fetch/BodyStreamBuffer.h" 15 #include "modules/fetch/BodyStreamBuffer.h"
17 #include "modules/fetch/BytesConsumer.h" 16 #include "modules/fetch/BytesConsumer.h"
18 #include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" 17 #include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
19 #include "platform/RuntimeEnabledFeatures.h" 18 #include "modules/serviceworkers/WaitUntilObserver.h"
20 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h" 19 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
21 #include "v8/include/v8.h"
22 #include "wtf/Assertions.h"
23 #include "wtf/RefPtr.h"
24 20
25 namespace blink { 21 namespace blink {
26 namespace { 22 namespace {
27 23
28 // Returns the error message to let the developer know about the reason of the 24 // Returns the error message to let the developer know about the reason of the
29 // unusual failures. 25 // unusual failures.
30 const String getMessageForResponseError(WebServiceWorkerResponseError error, 26 const String getMessageForResponseError(WebServiceWorkerResponseError error,
31 const KURL& requestURL) { 27 const KURL& requestURL) {
32 String errorMessage = "The FetchEvent for \"" + requestURL.getString() + 28 String errorMessage = "The FetchEvent for \"" + requestURL.getString() +
33 "\" resulted in a network error response: "; 29 "\" resulted in a network error response: ";
(...skipping 14 matching lines...) Expand all
48 case WebServiceWorkerResponseErrorResponseTypeError: 44 case WebServiceWorkerResponseErrorResponseTypeError:
49 errorMessage = errorMessage + 45 errorMessage = errorMessage +
50 "the promise was resolved with an error response object."; 46 "the promise was resolved with an error response object.";
51 break; 47 break;
52 case WebServiceWorkerResponseErrorResponseTypeOpaque: 48 case WebServiceWorkerResponseErrorResponseTypeOpaque:
53 errorMessage = errorMessage + 49 errorMessage = errorMessage +
54 "an \"opaque\" response was used for a request whose type " 50 "an \"opaque\" response was used for a request whose type "
55 "is not no-cors"; 51 "is not no-cors";
56 break; 52 break;
57 case WebServiceWorkerResponseErrorResponseTypeNotBasicOrDefault: 53 case WebServiceWorkerResponseErrorResponseTypeNotBasicOrDefault:
58 ASSERT_NOT_REACHED(); 54 NOTREACHED();
59 break; 55 break;
60 case WebServiceWorkerResponseErrorBodyUsed: 56 case WebServiceWorkerResponseErrorBodyUsed:
61 errorMessage = errorMessage + 57 errorMessage = errorMessage +
62 "a Response whose \"bodyUsed\" is \"true\" cannot be used " 58 "a Response whose \"bodyUsed\" is \"true\" cannot be used "
63 "to respond to a request."; 59 "to respond to a request.";
64 break; 60 break;
65 case WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest: 61 case WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest:
66 errorMessage = errorMessage + 62 errorMessage = errorMessage +
67 "an \"opaque\" response was used for a client request."; 63 "an \"opaque\" response was used for a client request.";
68 break; 64 break;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 134
139 public: 135 public:
140 NoopLoaderClient() = default; 136 NoopLoaderClient() = default;
141 void didFetchDataLoadedStream() override {} 137 void didFetchDataLoadedStream() override {}
142 void didFetchDataLoadFailed() override {} 138 void didFetchDataLoadFailed() override {}
143 DEFINE_INLINE_TRACE() { FetchDataLoader::Client::trace(visitor); } 139 DEFINE_INLINE_TRACE() { FetchDataLoader::Client::trace(visitor); }
144 }; 140 };
145 141
146 } // namespace 142 } // namespace
147 143
148 class RespondWithObserver::ThenFunction final : public ScriptFunction { 144 FetchRespondWithObserver* FetchRespondWithObserver::create(
149 public:
150 enum ResolveType {
151 Fulfilled,
152 Rejected,
153 };
154
155 static v8::Local<v8::Function> createFunction(ScriptState* scriptState,
156 RespondWithObserver* observer,
157 ResolveType type) {
158 ThenFunction* self = new ThenFunction(scriptState, observer, type);
159 return self->bindToV8Function();
160 }
161
162 DEFINE_INLINE_VIRTUAL_TRACE() {
163 visitor->trace(m_observer);
164 ScriptFunction::trace(visitor);
165 }
166
167 private:
168 ThenFunction(ScriptState* scriptState,
169 RespondWithObserver* observer,
170 ResolveType type)
171 : ScriptFunction(scriptState),
172 m_observer(observer),
173 m_resolveType(type) {}
174
175 ScriptValue call(ScriptValue value) override {
176 ASSERT(m_observer);
177 ASSERT(m_resolveType == Fulfilled || m_resolveType == Rejected);
178 if (m_resolveType == Rejected) {
179 m_observer->responseWasRejected(
180 WebServiceWorkerResponseErrorPromiseRejected);
181 value =
182 ScriptPromise::reject(value.getScriptState(), value).getScriptValue();
183 } else {
184 m_observer->responseWasFulfilled(value);
185 }
186 m_observer = nullptr;
187 return value;
188 }
189
190 Member<RespondWithObserver> m_observer;
191 ResolveType m_resolveType;
192 };
193
194 RespondWithObserver::~RespondWithObserver() {}
195
196 RespondWithObserver* RespondWithObserver::create(
197 ExecutionContext* context, 145 ExecutionContext* context,
198 int fetchEventID, 146 int fetchEventID,
199 const KURL& requestURL, 147 const KURL& requestURL,
200 WebURLRequest::FetchRequestMode requestMode, 148 WebURLRequest::FetchRequestMode requestMode,
201 WebURLRequest::FetchRedirectMode redirectMode, 149 WebURLRequest::FetchRedirectMode redirectMode,
202 WebURLRequest::FrameType frameType, 150 WebURLRequest::FrameType frameType,
203 WebURLRequest::RequestContext requestContext, 151 WebURLRequest::RequestContext requestContext,
204 WaitUntilObserver* observer) { 152 WaitUntilObserver* observer) {
205 return new RespondWithObserver(context, fetchEventID, requestURL, requestMode, 153 return new FetchRespondWithObserver(context, fetchEventID, requestURL,
206 redirectMode, frameType, requestContext, 154 requestMode, redirectMode, frameType,
207 observer); 155 requestContext, observer);
208 } 156 }
209 157
210 void RespondWithObserver::contextDestroyed(ExecutionContext*) { 158 void FetchRespondWithObserver::onResponseRejected(
211 if (m_observer) {
212 DCHECK_EQ(Pending, m_state);
213 m_observer.clear();
214 }
215 m_state = Done;
216 }
217
218 void RespondWithObserver::willDispatchEvent() {
219 m_eventDispatchTime = WTF::currentTime();
220 }
221
222 void RespondWithObserver::didDispatchEvent(DispatchEventResult dispatchResult) {
223 ASSERT(getExecutionContext());
224 if (m_state != Initial)
225 return;
226
227 if (dispatchResult != DispatchEventResult::NotCanceled) {
228 m_observer->incrementPendingActivity();
229 responseWasRejected(WebServiceWorkerResponseErrorDefaultPrevented);
230 return;
231 }
232
233 ServiceWorkerGlobalScopeClient::from(getExecutionContext())
234 ->respondToFetchEvent(m_fetchEventID, m_eventDispatchTime);
235 m_state = Done;
236 m_observer.clear();
237 }
238
239 void RespondWithObserver::respondWith(ScriptState* scriptState,
240 ScriptPromise scriptPromise,
241 ExceptionState& exceptionState) {
242 if (m_state != Initial) {
243 exceptionState.throwDOMException(
244 InvalidStateError, "The fetch event has already been responded to.");
245 return;
246 }
247
248 m_state = Pending;
249 m_observer->incrementPendingActivity();
250 scriptPromise.then(
251 ThenFunction::createFunction(scriptState, this, ThenFunction::Fulfilled),
252 ThenFunction::createFunction(scriptState, this, ThenFunction::Rejected));
253 }
254
255 void RespondWithObserver::responseWasRejected(
256 WebServiceWorkerResponseError error) { 159 WebServiceWorkerResponseError error) {
257 ASSERT(getExecutionContext()); 160 DCHECK(getExecutionContext());
258 getExecutionContext()->addConsoleMessage( 161 getExecutionContext()->addConsoleMessage(
259 ConsoleMessage::create(JSMessageSource, WarningMessageLevel, 162 ConsoleMessage::create(JSMessageSource, WarningMessageLevel,
260 getMessageForResponseError(error, m_requestURL))); 163 getMessageForResponseError(error, m_requestURL)));
261 164
262 // The default value of WebServiceWorkerResponse's status is 0, which maps 165 // The default value of WebServiceWorkerResponse's status is 0, which maps
263 // to a network error. 166 // to a network error.
264 WebServiceWorkerResponse webResponse; 167 WebServiceWorkerResponse webResponse;
265 webResponse.setError(error); 168 webResponse.setError(error);
266 ServiceWorkerGlobalScopeClient::from(getExecutionContext()) 169 ServiceWorkerGlobalScopeClient::from(getExecutionContext())
267 ->respondToFetchEvent(m_fetchEventID, webResponse, m_eventDispatchTime); 170 ->respondToFetchEvent(m_eventID, webResponse, m_eventDispatchTime);
268 m_state = Done;
269 m_observer->decrementPendingActivity();
270 m_observer.clear();
271 } 171 }
272 172
273 void RespondWithObserver::responseWasFulfilled(const ScriptValue& value) { 173 void FetchRespondWithObserver::onResponseFulfilled(const ScriptValue& value) {
274 ASSERT(getExecutionContext()); 174 DCHECK(getExecutionContext());
275 if (!V8Response::hasInstance(value.v8Value(), 175 if (!V8Response::hasInstance(value.v8Value(),
276 toIsolate(getExecutionContext()))) { 176 toIsolate(getExecutionContext()))) {
277 responseWasRejected(WebServiceWorkerResponseErrorNoV8Instance); 177 onResponseRejected(WebServiceWorkerResponseErrorNoV8Instance);
278 return; 178 return;
279 } 179 }
280 Response* response = V8Response::toImplWithTypeCheck( 180 Response* response = V8Response::toImplWithTypeCheck(
281 toIsolate(getExecutionContext()), value.v8Value()); 181 toIsolate(getExecutionContext()), value.v8Value());
282 // "If one of the following conditions is true, return a network error: 182 // "If one of the following conditions is true, return a network error:
283 // - |response|'s type is |error|. 183 // - |response|'s type is |error|.
284 // - |request|'s mode is not |no-cors| and response's type is |opaque|. 184 // - |request|'s mode is not |no-cors| and response's type is |opaque|.
285 // - |request| is a client request and |response|'s type is neither 185 // - |request| is a client request and |response|'s type is neither
286 // |basic| nor |default|." 186 // |basic| nor |default|."
287 const FetchResponseData::Type responseType = response->response()->getType(); 187 const FetchResponseData::Type responseType = response->response()->getType();
288 if (responseType == FetchResponseData::ErrorType) { 188 if (responseType == FetchResponseData::ErrorType) {
289 responseWasRejected(WebServiceWorkerResponseErrorResponseTypeError); 189 onResponseRejected(WebServiceWorkerResponseErrorResponseTypeError);
290 return; 190 return;
291 } 191 }
292 if (responseType == FetchResponseData::OpaqueType) { 192 if (responseType == FetchResponseData::OpaqueType) {
293 if (m_requestMode != WebURLRequest::FetchRequestModeNoCORS) { 193 if (m_requestMode != WebURLRequest::FetchRequestModeNoCORS) {
294 responseWasRejected(WebServiceWorkerResponseErrorResponseTypeOpaque); 194 onResponseRejected(WebServiceWorkerResponseErrorResponseTypeOpaque);
295 return; 195 return;
296 } 196 }
297 197
298 // The request mode of client requests should be "same-origin" but it is 198 // The request mode of client requests should be "same-origin" but it is
299 // not explicitly stated in the spec yet. So we need to check here. 199 // not explicitly stated in the spec yet. So we need to check here.
300 // FIXME: Set the request mode of client requests to "same-origin" and 200 // FIXME: Set the request mode of client requests to "same-origin" and
301 // remove this check when the spec will be updated. 201 // remove this check when the spec will be updated.
302 // Spec issue: https://github.com/whatwg/fetch/issues/101 202 // Spec issue: https://github.com/whatwg/fetch/issues/101
303 if (isClientRequest(m_frameType, m_requestContext)) { 203 if (isClientRequest(m_frameType, m_requestContext)) {
304 responseWasRejected( 204 onResponseRejected(
305 WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest); 205 WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest);
306 return; 206 return;
307 } 207 }
308 } 208 }
309 if (m_redirectMode != WebURLRequest::FetchRedirectModeManual && 209 if (m_redirectMode != WebURLRequest::FetchRedirectModeManual &&
310 responseType == FetchResponseData::OpaqueRedirectType) { 210 responseType == FetchResponseData::OpaqueRedirectType) {
311 responseWasRejected( 211 onResponseRejected(WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect);
312 WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect);
313 return; 212 return;
314 } 213 }
315 if (m_redirectMode != WebURLRequest::FetchRedirectModeFollow && 214 if (m_redirectMode != WebURLRequest::FetchRedirectModeFollow &&
316 response->redirected()) { 215 response->redirected()) {
317 if (!isNavigationRequest(m_frameType)) { 216 if (!isNavigationRequest(m_frameType)) {
318 responseWasRejected( 217 onResponseRejected(
319 WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest); 218 WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest);
320 return; 219 return;
321 } 220 }
322 // TODO(horo): We should just reject even if the request was a navigation. 221 // TODO(horo): We should just reject even if the request was a navigation.
323 // Currently we measure the impact of the restriction with the use counter 222 // Currently we measure the impact of the restriction with the use counter
324 // in DocumentLoader. 223 // in DocumentLoader.
325 getExecutionContext()->addConsoleMessage(ConsoleMessage::create( 224 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(
326 JSMessageSource, ErrorMessageLevel, 225 JSMessageSource, ErrorMessageLevel,
327 getErrorMessageForRedirectedResponseForNavigationRequest( 226 getErrorMessageForRedirectedResponseForNavigationRequest(
328 m_requestURL, response->internalURLList()))); 227 m_requestURL, response->internalURLList())));
329 } 228 }
330 if (response->isBodyLocked()) { 229 if (response->isBodyLocked()) {
331 responseWasRejected(WebServiceWorkerResponseErrorBodyLocked); 230 onResponseRejected(WebServiceWorkerResponseErrorBodyLocked);
332 return; 231 return;
333 } 232 }
334 if (response->bodyUsed()) { 233 if (response->bodyUsed()) {
335 responseWasRejected(WebServiceWorkerResponseErrorBodyUsed); 234 onResponseRejected(WebServiceWorkerResponseErrorBodyUsed);
336 return; 235 return;
337 } 236 }
338 237
339 WebServiceWorkerResponse webResponse; 238 WebServiceWorkerResponse webResponse;
340 response->populateWebServiceWorkerResponse(webResponse); 239 response->populateWebServiceWorkerResponse(webResponse);
341 BodyStreamBuffer* buffer = response->internalBodyBuffer(); 240 BodyStreamBuffer* buffer = response->internalBodyBuffer();
342 if (buffer) { 241 if (buffer) {
343 RefPtr<BlobDataHandle> blobDataHandle = buffer->drainAsBlobDataHandle( 242 RefPtr<BlobDataHandle> blobDataHandle = buffer->drainAsBlobDataHandle(
344 BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize); 243 BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize);
345 if (blobDataHandle) { 244 if (blobDataHandle) {
346 webResponse.setBlobDataHandle(blobDataHandle); 245 webResponse.setBlobDataHandle(blobDataHandle);
347 } else { 246 } else {
348 Stream* outStream = Stream::create(getExecutionContext(), ""); 247 Stream* outStream = Stream::create(getExecutionContext(), "");
349 webResponse.setStreamURL(outStream->url()); 248 webResponse.setStreamURL(outStream->url());
350 buffer->startLoading(FetchDataLoader::createLoaderAsStream(outStream), 249 buffer->startLoading(FetchDataLoader::createLoaderAsStream(outStream),
351 new NoopLoaderClient); 250 new NoopLoaderClient);
352 } 251 }
353 } 252 }
354 ServiceWorkerGlobalScopeClient::from(getExecutionContext()) 253 ServiceWorkerGlobalScopeClient::from(getExecutionContext())
355 ->respondToFetchEvent(m_fetchEventID, webResponse, m_eventDispatchTime); 254 ->respondToFetchEvent(m_eventID, webResponse, m_eventDispatchTime);
356 m_state = Done;
357 m_observer->decrementPendingActivity();
358 m_observer.clear();
359 } 255 }
360 256
361 RespondWithObserver::RespondWithObserver( 257 void FetchRespondWithObserver::onNoResponse() {
258 ServiceWorkerGlobalScopeClient::from(getExecutionContext())
259 ->respondToFetchEvent(m_eventID, m_eventDispatchTime);
260 }
261
262 FetchRespondWithObserver::FetchRespondWithObserver(
362 ExecutionContext* context, 263 ExecutionContext* context,
363 int fetchEventID, 264 int fetchEventID,
364 const KURL& requestURL, 265 const KURL& requestURL,
365 WebURLRequest::FetchRequestMode requestMode, 266 WebURLRequest::FetchRequestMode requestMode,
366 WebURLRequest::FetchRedirectMode redirectMode, 267 WebURLRequest::FetchRedirectMode redirectMode,
367 WebURLRequest::FrameType frameType, 268 WebURLRequest::FrameType frameType,
368 WebURLRequest::RequestContext requestContext, 269 WebURLRequest::RequestContext requestContext,
369 WaitUntilObserver* observer) 270 WaitUntilObserver* observer)
370 : ContextLifecycleObserver(context), 271 : RespondWithObserver(context, fetchEventID, observer),
371 m_fetchEventID(fetchEventID),
372 m_requestURL(requestURL), 272 m_requestURL(requestURL),
373 m_requestMode(requestMode), 273 m_requestMode(requestMode),
374 m_redirectMode(redirectMode), 274 m_redirectMode(redirectMode),
375 m_frameType(frameType), 275 m_frameType(frameType),
376 m_requestContext(requestContext), 276 m_requestContext(requestContext) {}
377 m_state(Initial),
378 m_observer(observer) {}
379 277
380 DEFINE_TRACE(RespondWithObserver) { 278 DEFINE_TRACE(FetchRespondWithObserver) {
381 visitor->trace(m_observer); 279 RespondWithObserver::trace(visitor);
382 ContextLifecycleObserver::trace(visitor);
383 } 280 }
384 281
385 } // namespace blink 282 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698