blob: f1f32dddf0a4fe3529f932e5b5c7d763a8d373a4 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/serviceworkers/ForeignFetchRespondWithObserver.h"
#include "bindings/modules/v8/V8ForeignFetchResponse.h"
#include "modules/fetch/Response.h"
#include "modules/serviceworkers/ForeignFetchResponse.h"
#include "public/platform/WebCORS.h"
#include "services/network/public/interfaces/fetch_api.mojom-blink.h"
using blink::mojom::ServiceWorkerResponseError;
namespace blink {
ForeignFetchRespondWithObserver* ForeignFetchRespondWithObserver::Create(
ExecutionContext* context,
int event_id,
const KURL& request_url,
network::mojom::FetchRequestMode request_mode,
WebURLRequest::FetchRedirectMode redirect_mode,
WebURLRequest::FrameType frame_type,
WebURLRequest::RequestContext request_context,
scoped_refptr<SecurityOrigin> request_origin,
WaitUntilObserver* observer) {
return new ForeignFetchRespondWithObserver(
context, event_id, request_url, request_mode, redirect_mode, frame_type,
request_context, std::move(request_origin), observer);
}
void ForeignFetchRespondWithObserver::OnResponseFulfilled(
const ScriptValue& value) {
DCHECK(GetExecutionContext());
ExceptionState exception_state(value.GetIsolate(),
ExceptionState::kUnknownContext,
"ForeignFetchEvent", "respondWith");
ForeignFetchResponse foreign_fetch_response =
ScriptValue::To<ForeignFetchResponse>(ToIsolate(GetExecutionContext()),
value, exception_state);
if (exception_state.HadException()) {
exception_state.ClearException();
OnResponseRejected(ServiceWorkerResponseError::kNoForeignFetchResponse);
return;
}
Response* response = foreign_fetch_response.response();
const FetchResponseData* internal_response = response->GetResponse();
const bool is_opaque = internal_response->GetType() ==
network::mojom::FetchResponseType::kOpaque ||
internal_response->GetType() ==
network::mojom::FetchResponseType::kOpaqueRedirect;
if (internal_response->GetType() !=
network::mojom::FetchResponseType::kDefault)
internal_response = internal_response->InternalResponse();
if (!foreign_fetch_response.hasOrigin()) {
if (foreign_fetch_response.hasHeaders() &&
!foreign_fetch_response.headers().IsEmpty()) {
OnResponseRejected(
ServiceWorkerResponseError::kForeignFetchHeadersWithoutOrigin);
return;
}
// If response isn't already opaque, make it opaque.
if (!is_opaque) {
FetchResponseData* opaque_data =
internal_response->CreateOpaqueFilteredResponse();
response = Response::Create(GetExecutionContext(), opaque_data);
}
} else if (request_origin_->ToString() != foreign_fetch_response.origin()) {
OnResponseRejected(
ServiceWorkerResponseError::kForeignFetchMismatchedOrigin);
return;
} else if (!is_opaque) {
WebHTTPHeaderSet headers;
if (foreign_fetch_response.hasHeaders()) {
for (const String& header : foreign_fetch_response.headers())
headers.emplace(header.Ascii().data(), header.Ascii().length());
if (response->GetResponse()->GetType() ==
network::mojom::FetchResponseType::kCORS) {
const WebHTTPHeaderSet& existing_headers =
response->GetResponse()->CorsExposedHeaderNames();
for (WebHTTPHeaderSet::iterator it = headers.begin();
it != headers.end();) {
if (existing_headers.find(*it) == existing_headers.end()) {
it = headers.erase(it);
} else {
++it;
}
}
}
}
FetchResponseData* response_data =
internal_response->CreateCORSFilteredResponse(headers);
response = Response::Create(GetExecutionContext(), response_data);
}
FetchRespondWithObserver::OnResponseFulfilled(
ScriptValue::From(value.GetScriptState(), response));
}
ForeignFetchRespondWithObserver::ForeignFetchRespondWithObserver(
ExecutionContext* context,
int event_id,
const KURL& request_url,
network::mojom::FetchRequestMode request_mode,
WebURLRequest::FetchRedirectMode redirect_mode,
WebURLRequest::FrameType frame_type,
WebURLRequest::RequestContext request_context,
scoped_refptr<SecurityOrigin> request_origin,
WaitUntilObserver* observer)
: FetchRespondWithObserver(context,
event_id,
request_url,
request_mode,
redirect_mode,
frame_type,
request_context,
observer),
request_origin_(std::move(request_origin)) {}
} // namespace blink