mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1173912 Fail opaque responses for client requests. r=ehsan
This commit is contained in:
parent
cc4c8b3dd4
commit
1d8798cbc9
@ -5203,6 +5203,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||
case NS_ERROR_BAD_OPAQUE_INTERCEPTION_REQUEST_MODE:
|
||||
case NS_ERROR_INTERCEPTED_ERROR_RESPONSE:
|
||||
case NS_ERROR_INTERCEPTED_USED_RESPONSE:
|
||||
case NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION:
|
||||
// ServiceWorker intercepted request, but something went wrong.
|
||||
nsContentUtils::MaybeReportInterceptionErrorToConsole(GetDocument(),
|
||||
aError);
|
||||
@ -7840,6 +7841,7 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
||||
aStatus == NS_ERROR_BAD_OPAQUE_INTERCEPTION_REQUEST_MODE ||
|
||||
aStatus == NS_ERROR_INTERCEPTED_ERROR_RESPONSE ||
|
||||
aStatus == NS_ERROR_INTERCEPTED_USED_RESPONSE ||
|
||||
aStatus == NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION ||
|
||||
NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
|
||||
// Errors to be shown for any frame
|
||||
DisplayLoadError(aStatus, url, nullptr, aChannel);
|
||||
|
@ -3432,6 +3432,8 @@ nsContentUtils::MaybeReportInterceptionErrorToConsole(nsIDocument* aDocument,
|
||||
messageName = "InterceptedErrorResponse";
|
||||
} else if (aError == NS_ERROR_INTERCEPTED_USED_RESPONSE) {
|
||||
messageName = "InterceptedUsedResponse";
|
||||
} else if (aError == NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION) {
|
||||
messageName = "ClientRequestOpaqueInterception";
|
||||
}
|
||||
|
||||
if (messageName) {
|
||||
|
@ -195,5 +195,44 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
|
||||
return context;
|
||||
}
|
||||
|
||||
bool
|
||||
InternalRequest::IsNavigationRequest() const
|
||||
{
|
||||
// https://fetch.spec.whatwg.org/#navigation-request-context
|
||||
//
|
||||
// A navigation request context is one of "form", "frame", "hyperlink",
|
||||
// "iframe", "internal" (as long as context frame type is not "none"),
|
||||
// "location", "metarefresh", and "prerender".
|
||||
//
|
||||
// TODO: include equivalent check for "form" context
|
||||
// TODO: include equivalent check for "prerender" context
|
||||
return mContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
||||
mContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
|
||||
mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
|
||||
mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
|
||||
mContentPolicyType == nsIContentPolicy::TYPE_REFRESH;
|
||||
}
|
||||
|
||||
bool
|
||||
InternalRequest::IsWorkerRequest() const
|
||||
{
|
||||
// https://fetch.spec.whatwg.org/#worker-request-context
|
||||
//
|
||||
// A worker request context is one of "serviceworker", "sharedworker", and
|
||||
// "worker".
|
||||
//
|
||||
// Note, service workers are not included here because currently there is
|
||||
// no way to generate a Request with a "serviceworker" RequestContext.
|
||||
// ServiceWorker scripts cannot be intercepted.
|
||||
return mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
|
||||
mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
|
||||
}
|
||||
|
||||
bool
|
||||
InternalRequest::IsClientRequest() const
|
||||
{
|
||||
return IsNavigationRequest() || IsWorkerRequest();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -356,6 +356,16 @@ public:
|
||||
mCreatedByFetchEvent = false;
|
||||
}
|
||||
|
||||
bool
|
||||
IsNavigationRequest() const;
|
||||
|
||||
bool
|
||||
IsWorkerRequest() const;
|
||||
|
||||
bool
|
||||
IsClientRequest() const;
|
||||
|
||||
|
||||
private:
|
||||
// Does not copy mBodyStream. Use fallible Clone() for complete copy.
|
||||
explicit InternalRequest(const InternalRequest& aOther);
|
||||
|
@ -176,3 +176,5 @@ BadOpaqueInterceptionRequestMode=A ServiceWorker passed an opaque Response to Fe
|
||||
InterceptedErrorResponse=A ServiceWorker passed an Error Response to FetchEvent.respondWith(). This typically means the ServiceWorker performed an invalid fetch() call.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "Response", "FetchEvent.respondWith()", or "Response.clone()".
|
||||
InterceptedUsedResponse=A ServiceWorker passed a used Response to FetchEvent.respondWith(). The body of a Response may only be read once. Use Response.clone() to access the body multiple times.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "Response", "FetchEvent.respondWith()", "FetchEvent.request", or "Worker".
|
||||
ClientRequestOpaqueInterception=A ServiceWorker passed an opaque Response to FetchEvent.respondWith() while FetchEvent.request was a client request. A client request is generally a browser navigation or top-level Worker script.
|
||||
|
@ -149,15 +149,17 @@ class RespondWithHandler final : public PromiseNativeHandler
|
||||
nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
|
||||
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
|
||||
RequestMode mRequestMode;
|
||||
bool mIsClientRequest;
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
RespondWithHandler(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
|
||||
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
|
||||
RequestMode aRequestMode)
|
||||
RequestMode aRequestMode, bool aIsClientRequest)
|
||||
: mInterceptedChannel(aChannel)
|
||||
, mServiceWorker(aServiceWorker)
|
||||
, mRequestMode(aRequestMode)
|
||||
, mIsClientRequest(aIsClientRequest)
|
||||
{
|
||||
}
|
||||
|
||||
@ -262,15 +264,26 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
|
||||
return;
|
||||
}
|
||||
|
||||
// Section 4.2, step 2.2 "If either response's type is "opaque" and request's
|
||||
// mode is not "no-cors" or response's type is error, return a network error."
|
||||
// Section 4.2, step 2.2:
|
||||
// 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".
|
||||
|
||||
if (response->Type() == ResponseType::Error) {
|
||||
autoCancel.SetCancelStatus(NS_ERROR_INTERCEPTED_ERROR_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response->Type() == ResponseType::Opaque && mRequestMode != RequestMode::No_cors) {
|
||||
autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_INTERCEPTION_REQUEST_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response->Type() == ResponseType::Error) {
|
||||
autoCancel.SetCancelStatus(NS_ERROR_INTERCEPTED_ERROR_RESPONSE);
|
||||
if (mIsClientRequest && response->Type() != ResponseType::Basic &&
|
||||
response->Type() != ResponseType::Default) {
|
||||
autoCancel.SetCancelStatus(NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -357,9 +370,11 @@ FetchEvent::RespondWith(const ResponseOrPromise& aArg, ErrorResult& aRv)
|
||||
} else if (aArg.IsPromise()) {
|
||||
promise = &aArg.GetAsPromise();
|
||||
}
|
||||
nsRefPtr<InternalRequest> ir = mRequest->GetInternalRequest();
|
||||
mWaitToRespond = true;
|
||||
nsRefPtr<RespondWithHandler> handler =
|
||||
new RespondWithHandler(mChannel, mServiceWorker, mRequest->Mode());
|
||||
new RespondWithHandler(mChannel, mServiceWorker, mRequest->Mode(),
|
||||
ir->IsClientRequest());
|
||||
promise->AppendNativeHandler(handler);
|
||||
}
|
||||
|
||||
|
Binary file not shown.
@ -21,10 +21,12 @@ function runTests() {
|
||||
return testFetchAppResource('test_custom_content_type',
|
||||
'customContentType', 'text/html');
|
||||
})
|
||||
.then(testRedirectedResponse)
|
||||
.then(testRedirectedHttpsResponse)
|
||||
.then(testCachedRedirectedResponse)
|
||||
.then(testCachedRedirectedHttpsResponse)
|
||||
// XXX: Cross-origin interceptions without CORS result in opaque responses
|
||||
// which are illegal for navigations like iframes. (bug 1183313)
|
||||
//.then(testRedirectedResponse)
|
||||
//.then(testRedirectedHttpsResponse)
|
||||
//.then(testCachedRedirectedResponse)
|
||||
//.then(testCachedRedirectedHttpsResponse)
|
||||
.then(done);
|
||||
}
|
||||
</script>
|
||||
|
@ -331,6 +331,8 @@
|
||||
ERROR(NS_ERROR_INTERCEPTED_ERROR_RESPONSE, FAILURE(103)),
|
||||
/* Service worker intercepted with a response with bodyUsed set to true */
|
||||
ERROR(NS_ERROR_INTERCEPTED_USED_RESPONSE, FAILURE(104)),
|
||||
/* Service worker intercepted a client request with an opaque response */
|
||||
ERROR(NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION, FAILURE(105)),
|
||||
#undef MODULE
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user