mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1184967 P1 Set RequestMode based on LoadInfo securityMode and client request content policy. r=nsm
This commit is contained in:
parent
293122e98b
commit
6fa0c8de16
@ -206,8 +206,9 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
bool
|
bool
|
||||||
InternalRequest::IsNavigationRequest() const
|
InternalRequest::IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType)
|
||||||
{
|
{
|
||||||
// https://fetch.spec.whatwg.org/#navigation-request-context
|
// https://fetch.spec.whatwg.org/#navigation-request-context
|
||||||
//
|
//
|
||||||
@ -215,17 +216,22 @@ InternalRequest::IsNavigationRequest() const
|
|||||||
// "iframe", "internal" (as long as context frame type is not "none"),
|
// "iframe", "internal" (as long as context frame type is not "none"),
|
||||||
// "location", "metarefresh", and "prerender".
|
// "location", "metarefresh", and "prerender".
|
||||||
//
|
//
|
||||||
// TODO: include equivalent check for "form" context
|
// Note, all of these request types are effectively initiated by nsDocShell.
|
||||||
// TODO: include equivalent check for "prerender" context
|
//
|
||||||
return mContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
// The TYPE_REFRESH is used in some code paths for metarefresh, but will not
|
||||||
mContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
|
// be seen during the actual load. Instead the new load gets a normal
|
||||||
mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
|
// nsDocShell policy type. We include it here in case this utility method
|
||||||
mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
|
// is called before the load starts.
|
||||||
mContentPolicyType == nsIContentPolicy::TYPE_REFRESH;
|
return aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
||||||
|
aContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
|
||||||
|
aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
|
||||||
|
aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
|
||||||
|
aContentPolicyType == nsIContentPolicy::TYPE_REFRESH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
bool
|
bool
|
||||||
InternalRequest::IsWorkerRequest() const
|
InternalRequest::IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType)
|
||||||
{
|
{
|
||||||
// https://fetch.spec.whatwg.org/#worker-request-context
|
// https://fetch.spec.whatwg.org/#worker-request-context
|
||||||
//
|
//
|
||||||
@ -235,8 +241,20 @@ InternalRequest::IsWorkerRequest() const
|
|||||||
// Note, service workers are not included here because currently there is
|
// Note, service workers are not included here because currently there is
|
||||||
// no way to generate a Request with a "serviceworker" RequestContext.
|
// no way to generate a Request with a "serviceworker" RequestContext.
|
||||||
// ServiceWorker scripts cannot be intercepted.
|
// ServiceWorker scripts cannot be intercepted.
|
||||||
return mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
|
return aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
|
||||||
mContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
|
aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
InternalRequest::IsNavigationRequest() const
|
||||||
|
{
|
||||||
|
return IsNavigationContentPolicy(mContentPolicyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
InternalRequest::IsWorkerRequest() const
|
||||||
|
{
|
||||||
|
return IsWorkerContentPolicy(mContentPolicyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -245,5 +263,63 @@ InternalRequest::IsClientRequest() const
|
|||||||
return IsNavigationRequest() || IsWorkerRequest();
|
return IsNavigationRequest() || IsWorkerRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
RequestMode
|
||||||
|
InternalRequest::MapChannelToRequestMode(nsIChannel* aChannel)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aChannel);
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aChannel->GetLoadInfo(getter_AddRefs(loadInfo))));
|
||||||
|
|
||||||
|
// RequestMode deviates from our internal security mode for navigations.
|
||||||
|
// While navigations normally allow cross origin we must set a same-origin
|
||||||
|
// RequestMode to get the correct service worker interception restrictions
|
||||||
|
// in place.
|
||||||
|
// TODO: remove the worker override once securityMode is fully implemented (bug 1189945)
|
||||||
|
nsContentPolicyType contentPolicy = loadInfo->InternalContentPolicyType();
|
||||||
|
if (IsNavigationContentPolicy(contentPolicy) ||
|
||||||
|
IsWorkerContentPolicy(contentPolicy)) {
|
||||||
|
return RequestMode::Same_origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t securityMode;
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(loadInfo->GetSecurityMode(&securityMode)));
|
||||||
|
|
||||||
|
switch(securityMode) {
|
||||||
|
case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS:
|
||||||
|
case nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED:
|
||||||
|
return RequestMode::Same_origin;
|
||||||
|
case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS:
|
||||||
|
case nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL:
|
||||||
|
return RequestMode::No_cors;
|
||||||
|
case nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS:
|
||||||
|
// TODO: Check additional flag force-preflight after bug 1199693 (bug 1189945)
|
||||||
|
return RequestMode::Cors;
|
||||||
|
default:
|
||||||
|
// TODO: assert never reached after CorsMode flag removed (bug 1189945)
|
||||||
|
MOZ_ASSERT(securityMode == nsILoadInfo::SEC_NORMAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove following code once securityMode is fully implemented (bug 1189945)
|
||||||
|
|
||||||
|
// We only support app:// protocol interception in non-release builds.
|
||||||
|
#ifndef RELEASE_BUILD
|
||||||
|
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aChannel);
|
||||||
|
if (jarChannel) {
|
||||||
|
return RequestMode::No_cors;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(aChannel);
|
||||||
|
|
||||||
|
uint32_t corsMode;
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(httpChannel->GetCorsMode(&corsMode)));
|
||||||
|
|
||||||
|
// This cast is valid due to static asserts in ServiceWorkerManager.cpp.
|
||||||
|
return static_cast<RequestMode>(corsMode);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -377,6 +377,8 @@ public:
|
|||||||
bool
|
bool
|
||||||
IsClientRequest() const;
|
IsClientRequest() const;
|
||||||
|
|
||||||
|
static RequestMode
|
||||||
|
MapChannelToRequestMode(nsIChannel* aChannel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Does not copy mBodyStream. Use fallible Clone() for complete copy.
|
// Does not copy mBodyStream. Use fallible Clone() for complete copy.
|
||||||
@ -387,6 +389,12 @@ private:
|
|||||||
static RequestContext
|
static RequestContext
|
||||||
MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType);
|
MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType);
|
||||||
|
|
||||||
nsCString mMethod;
|
nsCString mMethod;
|
||||||
// mURL always stores the url with the ref stripped
|
// mURL always stores the url with the ref stripped
|
||||||
nsCString mURL;
|
nsCString mURL;
|
||||||
|
@ -150,7 +150,7 @@ class RespondWithHandler final : public PromiseNativeHandler
|
|||||||
nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
|
nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
|
||||||
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
|
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
|
||||||
const RequestMode mRequestMode;
|
const RequestMode mRequestMode;
|
||||||
const bool mIsClientRequest;
|
const DebugOnly<bool> mIsClientRequest;
|
||||||
const bool mIsNavigationRequest;
|
const bool mIsNavigationRequest;
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
@ -272,8 +272,6 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
|
|||||||
// If one of the following conditions is true, return a network error:
|
// If one of the following conditions is true, return a network error:
|
||||||
// * response's type is "error".
|
// * response's type is "error".
|
||||||
// * request's mode is not "no-cors" and response's type is "opaque".
|
// * 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".
|
|
||||||
// * request is not a navigation request and response's type is
|
// * request is not a navigation request and response's type is
|
||||||
// "opaqueredirect".
|
// "opaqueredirect".
|
||||||
|
|
||||||
@ -282,19 +280,13 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT_IF(mIsClientRequest, mRequestMode == RequestMode::Same_origin);
|
||||||
|
|
||||||
if (response->Type() == ResponseType::Opaque && mRequestMode != RequestMode::No_cors) {
|
if (response->Type() == ResponseType::Opaque && mRequestMode != RequestMode::No_cors) {
|
||||||
autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_INTERCEPTION_REQUEST_MODE);
|
autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_INTERCEPTION_REQUEST_MODE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this case as its no longer in the spec (bug 1184967)
|
|
||||||
if (mIsClientRequest && response->Type() != ResponseType::Basic &&
|
|
||||||
response->Type() != ResponseType::Default &&
|
|
||||||
response->Type() != ResponseType::Opaqueredirect) {
|
|
||||||
autoCancel.SetCancelStatus(NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mIsNavigationRequest && response->Type() == ResponseType::Opaqueredirect) {
|
if (!mIsNavigationRequest && response->Type() == ResponseType::Opaqueredirect) {
|
||||||
autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_REDIRECT_INTERCEPTION);
|
autoCancel.SetCancelStatus(NS_ERROR_BAD_OPAQUE_REDIRECT_INTERCEPTION);
|
||||||
return;
|
return;
|
||||||
|
@ -3709,22 +3709,7 @@ public:
|
|||||||
nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(httpChannel);
|
nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(httpChannel);
|
||||||
NS_ENSURE_TRUE(internalChannel, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(internalChannel, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
uint32_t corsMode;
|
mRequestMode = InternalRequest::MapChannelToRequestMode(channel);
|
||||||
internalChannel->GetCorsMode(&corsMode);
|
|
||||||
switch (corsMode) {
|
|
||||||
case nsIHttpChannelInternal::CORS_MODE_SAME_ORIGIN:
|
|
||||||
mRequestMode = RequestMode::Same_origin;
|
|
||||||
break;
|
|
||||||
case nsIHttpChannelInternal::CORS_MODE_NO_CORS:
|
|
||||||
mRequestMode = RequestMode::No_cors;
|
|
||||||
break;
|
|
||||||
case nsIHttpChannelInternal::CORS_MODE_CORS:
|
|
||||||
case nsIHttpChannelInternal::CORS_MODE_CORS_WITH_FORCED_PREFLIGHT:
|
|
||||||
mRequestMode = RequestMode::Cors;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MOZ_CRASH("Unexpected CORS mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is safe due to static_asserts at top of file.
|
// This is safe due to static_asserts at top of file.
|
||||||
uint32_t redirectMode;
|
uint32_t redirectMode;
|
||||||
@ -3757,6 +3742,8 @@ public:
|
|||||||
|
|
||||||
mMethod = "GET";
|
mMethod = "GET";
|
||||||
|
|
||||||
|
mRequestMode = InternalRequest::MapChannelToRequestMode(channel);
|
||||||
|
|
||||||
if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
|
if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
|
||||||
mRequestCredentials = RequestCredentials::Omit;
|
mRequestCredentials = RequestCredentials::Omit;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user