| Index: third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
|
| diff --git a/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp b/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
|
| index abde40fe3f13b834c847d000bce79648f3322295..550df7e7462e6be25e1d1aea1739f66c9b7dddda 100644
|
| --- a/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
|
| +++ b/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp
|
| @@ -4,146 +4,17 @@
|
|
|
| #include "modules/serviceworkers/RespondWithObserver.h"
|
|
|
| +#include <v8.h>
|
| +
|
| #include "bindings/core/v8/ScriptFunction.h"
|
| #include "bindings/core/v8/ScriptPromise.h"
|
| #include "bindings/core/v8/ScriptValue.h"
|
| #include "bindings/core/v8/V8Binding.h"
|
| -#include "bindings/modules/v8/V8Response.h"
|
| -#include "core/dom/ExceptionCode.h"
|
| #include "core/dom/ExecutionContext.h"
|
| -#include "core/inspector/ConsoleMessage.h"
|
| -#include "core/streams/Stream.h"
|
| -#include "modules/fetch/BodyStreamBuffer.h"
|
| -#include "modules/fetch/BytesConsumer.h"
|
| -#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
|
| -#include "platform/RuntimeEnabledFeatures.h"
|
| +#include "modules/serviceworkers/WaitUntilObserver.h"
|
| #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
|
| -#include "v8/include/v8.h"
|
| -#include "wtf/Assertions.h"
|
| -#include "wtf/RefPtr.h"
|
|
|
| namespace blink {
|
| -namespace {
|
| -
|
| -// Returns the error message to let the developer know about the reason of the
|
| -// unusual failures.
|
| -const String getMessageForResponseError(WebServiceWorkerResponseError error,
|
| - const KURL& requestURL) {
|
| - String errorMessage = "The FetchEvent for \"" + requestURL.getString() +
|
| - "\" resulted in a network error response: ";
|
| - switch (error) {
|
| - case WebServiceWorkerResponseErrorPromiseRejected:
|
| - errorMessage = errorMessage + "the promise was rejected.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorDefaultPrevented:
|
| - errorMessage =
|
| - errorMessage +
|
| - "preventDefault() was called without calling respondWith().";
|
| - break;
|
| - case WebServiceWorkerResponseErrorNoV8Instance:
|
| - errorMessage =
|
| - errorMessage +
|
| - "an object that was not a Response was passed to respondWith().";
|
| - break;
|
| - case WebServiceWorkerResponseErrorResponseTypeError:
|
| - errorMessage = errorMessage +
|
| - "the promise was resolved with an error response object.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorResponseTypeOpaque:
|
| - errorMessage = errorMessage +
|
| - "an \"opaque\" response was used for a request whose type "
|
| - "is not no-cors";
|
| - break;
|
| - case WebServiceWorkerResponseErrorResponseTypeNotBasicOrDefault:
|
| - ASSERT_NOT_REACHED();
|
| - break;
|
| - case WebServiceWorkerResponseErrorBodyUsed:
|
| - errorMessage = errorMessage +
|
| - "a Response whose \"bodyUsed\" is \"true\" cannot be used "
|
| - "to respond to a request.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest:
|
| - errorMessage = errorMessage +
|
| - "an \"opaque\" response was used for a client request.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect:
|
| - errorMessage = errorMessage +
|
| - "an \"opaqueredirect\" type response was used for a "
|
| - "request whose redirect mode is not \"manual\".";
|
| - break;
|
| - case WebServiceWorkerResponseErrorBodyLocked:
|
| - errorMessage = errorMessage +
|
| - "a Response whose \"body\" is locked cannot be used to "
|
| - "respond to a request.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorNoForeignFetchResponse:
|
| - errorMessage = errorMessage +
|
| - "an object that was not a ForeignFetchResponse was passed "
|
| - "to respondWith().";
|
| - break;
|
| - case WebServiceWorkerResponseErrorForeignFetchHeadersWithoutOrigin:
|
| - errorMessage =
|
| - errorMessage +
|
| - "headers were specified for a response without an explicit origin.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorForeignFetchMismatchedOrigin:
|
| - errorMessage =
|
| - errorMessage + "origin in response does not match origin of request.";
|
| - break;
|
| - case WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest:
|
| - errorMessage = errorMessage +
|
| - "a redirected response was used for a request whose "
|
| - "redirect mode is not \"follow\".";
|
| - break;
|
| - case WebServiceWorkerResponseErrorUnknown:
|
| - default:
|
| - errorMessage = errorMessage + "an unexpected error occurred.";
|
| - break;
|
| - }
|
| - return errorMessage;
|
| -}
|
| -
|
| -const String getErrorMessageForRedirectedResponseForNavigationRequest(
|
| - const KURL& requestURL,
|
| - const Vector<KURL>& responseURLList) {
|
| - String errorMessage =
|
| - "In Chrome 59, the navigation to \"" + requestURL.getString() + "\" " +
|
| - "will result in a network error, because FetchEvent.respondWith() was " +
|
| - "called with a redirected response. See https://crbug.com/658249. The " +
|
| - "url list of the response was: [\"" + responseURLList[0].getString() +
|
| - "\"";
|
| - for (size_t i = 1; i < responseURLList.size(); ++i) {
|
| - errorMessage =
|
| - errorMessage + ", \"" + responseURLList[i].getString() + "\"";
|
| - }
|
| - return errorMessage + "]";
|
| -}
|
| -
|
| -bool isNavigationRequest(WebURLRequest::FrameType frameType) {
|
| - return frameType != WebURLRequest::FrameTypeNone;
|
| -}
|
| -
|
| -bool isClientRequest(WebURLRequest::FrameType frameType,
|
| - WebURLRequest::RequestContext requestContext) {
|
| - return isNavigationRequest(frameType) ||
|
| - requestContext == WebURLRequest::RequestContextSharedWorker ||
|
| - requestContext == WebURLRequest::RequestContextWorker;
|
| -}
|
| -
|
| -class NoopLoaderClient final
|
| - : public GarbageCollectedFinalized<NoopLoaderClient>,
|
| - public FetchDataLoader::Client {
|
| - WTF_MAKE_NONCOPYABLE(NoopLoaderClient);
|
| - USING_GARBAGE_COLLECTED_MIXIN(NoopLoaderClient);
|
| -
|
| - public:
|
| - NoopLoaderClient() = default;
|
| - void didFetchDataLoadedStream() override {}
|
| - void didFetchDataLoadFailed() override {}
|
| - DEFINE_INLINE_TRACE() { FetchDataLoader::Client::trace(visitor); }
|
| -};
|
| -
|
| -} // namespace
|
|
|
| class RespondWithObserver::ThenFunction final : public ScriptFunction {
|
| public:
|
| @@ -191,22 +62,6 @@ class RespondWithObserver::ThenFunction final : public ScriptFunction {
|
| ResolveType m_resolveType;
|
| };
|
|
|
| -RespondWithObserver::~RespondWithObserver() {}
|
| -
|
| -RespondWithObserver* RespondWithObserver::create(
|
| - ExecutionContext* context,
|
| - int fetchEventID,
|
| - const KURL& requestURL,
|
| - WebURLRequest::FetchRequestMode requestMode,
|
| - WebURLRequest::FetchRedirectMode redirectMode,
|
| - WebURLRequest::FrameType frameType,
|
| - WebURLRequest::RequestContext requestContext,
|
| - WaitUntilObserver* observer) {
|
| - return new RespondWithObserver(context, fetchEventID, requestURL, requestMode,
|
| - redirectMode, frameType, requestContext,
|
| - observer);
|
| -}
|
| -
|
| void RespondWithObserver::contextDestroyed(ExecutionContext*) {
|
| if (m_observer) {
|
| DCHECK_EQ(Pending, m_state);
|
| @@ -230,8 +85,7 @@ void RespondWithObserver::didDispatchEvent(DispatchEventResult dispatchResult) {
|
| return;
|
| }
|
|
|
| - ServiceWorkerGlobalScopeClient::from(getExecutionContext())
|
| - ->respondToFetchEvent(m_fetchEventID, m_eventDispatchTime);
|
| + onNoResponse();
|
| m_state = Done;
|
| m_observer.clear();
|
| }
|
| @@ -241,7 +95,7 @@ void RespondWithObserver::respondWith(ScriptState* scriptState,
|
| ExceptionState& exceptionState) {
|
| if (m_state != Initial) {
|
| exceptionState.throwDOMException(
|
| - InvalidStateError, "The fetch event has already been responded to.");
|
| + InvalidStateError, "The event has already been responded to.");
|
| return;
|
| }
|
|
|
| @@ -254,126 +108,24 @@ void RespondWithObserver::respondWith(ScriptState* scriptState,
|
|
|
| void RespondWithObserver::responseWasRejected(
|
| WebServiceWorkerResponseError error) {
|
| - ASSERT(getExecutionContext());
|
| - getExecutionContext()->addConsoleMessage(
|
| - ConsoleMessage::create(JSMessageSource, WarningMessageLevel,
|
| - getMessageForResponseError(error, m_requestURL)));
|
| -
|
| - // The default value of WebServiceWorkerResponse's status is 0, which maps
|
| - // to a network error.
|
| - WebServiceWorkerResponse webResponse;
|
| - webResponse.setError(error);
|
| - ServiceWorkerGlobalScopeClient::from(getExecutionContext())
|
| - ->respondToFetchEvent(m_fetchEventID, webResponse, m_eventDispatchTime);
|
| + onResponseRejected(error);
|
| m_state = Done;
|
| m_observer->decrementPendingActivity();
|
| m_observer.clear();
|
| }
|
|
|
| void RespondWithObserver::responseWasFulfilled(const ScriptValue& value) {
|
| - ASSERT(getExecutionContext());
|
| - if (!V8Response::hasInstance(value.v8Value(),
|
| - toIsolate(getExecutionContext()))) {
|
| - responseWasRejected(WebServiceWorkerResponseErrorNoV8Instance);
|
| - return;
|
| - }
|
| - Response* response = V8Response::toImplWithTypeCheck(
|
| - toIsolate(getExecutionContext()), value.v8Value());
|
| - // "If one of the following conditions is true, return a network error:
|
| - // - |response|'s type is |error|.
|
| - // - |request|'s mode is not |no-cors| and response's type is |opaque|.
|
| - // - |request| is a client request and |response|'s type is neither
|
| - // |basic| nor |default|."
|
| - const FetchResponseData::Type responseType = response->response()->getType();
|
| - if (responseType == FetchResponseData::ErrorType) {
|
| - responseWasRejected(WebServiceWorkerResponseErrorResponseTypeError);
|
| - return;
|
| - }
|
| - if (responseType == FetchResponseData::OpaqueType) {
|
| - if (m_requestMode != WebURLRequest::FetchRequestModeNoCORS) {
|
| - responseWasRejected(WebServiceWorkerResponseErrorResponseTypeOpaque);
|
| - return;
|
| - }
|
| -
|
| - // The request mode of client requests should be "same-origin" but it is
|
| - // not explicitly stated in the spec yet. So we need to check here.
|
| - // FIXME: Set the request mode of client requests to "same-origin" and
|
| - // remove this check when the spec will be updated.
|
| - // Spec issue: https://github.com/whatwg/fetch/issues/101
|
| - if (isClientRequest(m_frameType, m_requestContext)) {
|
| - responseWasRejected(
|
| - WebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest);
|
| - return;
|
| - }
|
| - }
|
| - if (m_redirectMode != WebURLRequest::FetchRedirectModeManual &&
|
| - responseType == FetchResponseData::OpaqueRedirectType) {
|
| - responseWasRejected(
|
| - WebServiceWorkerResponseErrorResponseTypeOpaqueRedirect);
|
| - return;
|
| - }
|
| - if (m_redirectMode != WebURLRequest::FetchRedirectModeFollow &&
|
| - response->redirected()) {
|
| - if (!isNavigationRequest(m_frameType)) {
|
| - responseWasRejected(
|
| - WebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest);
|
| - return;
|
| - }
|
| - // TODO(horo): We should just reject even if the request was a navigation.
|
| - // Currently we measure the impact of the restriction with the use counter
|
| - // in DocumentLoader.
|
| - getExecutionContext()->addConsoleMessage(ConsoleMessage::create(
|
| - JSMessageSource, ErrorMessageLevel,
|
| - getErrorMessageForRedirectedResponseForNavigationRequest(
|
| - m_requestURL, response->internalURLList())));
|
| - }
|
| - if (response->isBodyLocked()) {
|
| - responseWasRejected(WebServiceWorkerResponseErrorBodyLocked);
|
| - return;
|
| - }
|
| - if (response->bodyUsed()) {
|
| - responseWasRejected(WebServiceWorkerResponseErrorBodyUsed);
|
| - return;
|
| - }
|
| -
|
| - WebServiceWorkerResponse webResponse;
|
| - response->populateWebServiceWorkerResponse(webResponse);
|
| - BodyStreamBuffer* buffer = response->internalBodyBuffer();
|
| - if (buffer) {
|
| - RefPtr<BlobDataHandle> blobDataHandle = buffer->drainAsBlobDataHandle(
|
| - BytesConsumer::BlobSizePolicy::AllowBlobWithInvalidSize);
|
| - if (blobDataHandle) {
|
| - webResponse.setBlobDataHandle(blobDataHandle);
|
| - } else {
|
| - Stream* outStream = Stream::create(getExecutionContext(), "");
|
| - webResponse.setStreamURL(outStream->url());
|
| - buffer->startLoading(FetchDataLoader::createLoaderAsStream(outStream),
|
| - new NoopLoaderClient);
|
| - }
|
| - }
|
| - ServiceWorkerGlobalScopeClient::from(getExecutionContext())
|
| - ->respondToFetchEvent(m_fetchEventID, webResponse, m_eventDispatchTime);
|
| + onResponseFulfilled(value);
|
| m_state = Done;
|
| m_observer->decrementPendingActivity();
|
| m_observer.clear();
|
| }
|
|
|
| -RespondWithObserver::RespondWithObserver(
|
| - ExecutionContext* context,
|
| - int fetchEventID,
|
| - const KURL& requestURL,
|
| - WebURLRequest::FetchRequestMode requestMode,
|
| - WebURLRequest::FetchRedirectMode redirectMode,
|
| - WebURLRequest::FrameType frameType,
|
| - WebURLRequest::RequestContext requestContext,
|
| - WaitUntilObserver* observer)
|
| +RespondWithObserver::RespondWithObserver(ExecutionContext* context,
|
| + int eventID,
|
| + WaitUntilObserver* observer)
|
| : ContextLifecycleObserver(context),
|
| - m_fetchEventID(fetchEventID),
|
| - m_requestURL(requestURL),
|
| - m_requestMode(requestMode),
|
| - m_redirectMode(redirectMode),
|
| - m_frameType(frameType),
|
| - m_requestContext(requestContext),
|
| + m_eventID(eventID),
|
| m_state(Initial),
|
| m_observer(observer) {}
|
|
|
|
|