123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "InternalRequest.h"
- #include "nsIContentPolicy.h"
- #include "nsIDocument.h"
- #include "nsIHttpChannelInternal.h"
- #include "nsStreamUtils.h"
- #include "mozilla/ErrorResult.h"
- #include "mozilla/dom/FetchTypes.h"
- #include "mozilla/dom/ScriptSettings.h"
- #include "mozilla/dom/workers/Workers.h"
- #include "WorkerPrivate.h"
- namespace mozilla {
- namespace dom {
- // The global is used to extract the principal.
- already_AddRefed<InternalRequest>
- InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const
- {
- MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(), "Internal Request's urlList should not be empty when copied from constructor.");
- RefPtr<InternalRequest> copy = new InternalRequest(mURLList.LastElement(),
- mFragment);
- copy->SetMethod(mMethod);
- copy->mHeaders = new InternalHeaders(*mHeaders);
- copy->SetUnsafeRequest();
- copy->mBodyStream = mBodyStream;
- copy->mForceOriginHeader = true;
- // The "client" is not stored in our implementation. Fetch API users should
- // use the appropriate window/document/principal and other Gecko security
- // mechanisms as appropriate.
- copy->mSameOriginDataURL = true;
- copy->mPreserveContentCodings = true;
- copy->mReferrer = mReferrer;
- copy->mReferrerPolicy = mReferrerPolicy;
- copy->mEnvironmentReferrerPolicy = mEnvironmentReferrerPolicy;
- copy->mIntegrity = mIntegrity;
- copy->mContentPolicyType = mContentPolicyTypeOverridden ?
- mContentPolicyType :
- nsIContentPolicy::TYPE_FETCH;
- copy->mMode = mMode;
- copy->mCredentialsMode = mCredentialsMode;
- copy->mCacheMode = mCacheMode;
- copy->mRedirectMode = mRedirectMode;
- copy->mCreatedByFetchEvent = mCreatedByFetchEvent;
- copy->mContentPolicyTypeOverridden = mContentPolicyTypeOverridden;
- return copy.forget();
- }
- already_AddRefed<InternalRequest>
- InternalRequest::Clone()
- {
- RefPtr<InternalRequest> clone = new InternalRequest(*this);
- if (!mBodyStream) {
- return clone.forget();
- }
- nsCOMPtr<nsIInputStream> clonedBody;
- nsCOMPtr<nsIInputStream> replacementBody;
- nsresult rv = NS_CloneInputStream(mBodyStream, getter_AddRefs(clonedBody),
- getter_AddRefs(replacementBody));
- if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
- clone->mBodyStream.swap(clonedBody);
- if (replacementBody) {
- mBodyStream.swap(replacementBody);
- }
- return clone.forget();
- }
- InternalRequest::InternalRequest(const nsACString& aURL,
- const nsACString& aFragment)
- : mMethod("GET")
- , mHeaders(new InternalHeaders(HeadersGuardEnum::None))
- , mContentPolicyType(nsIContentPolicy::TYPE_FETCH)
- , mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
- , mReferrerPolicy(ReferrerPolicy::_empty)
- , mEnvironmentReferrerPolicy(net::RP_Default)
- , mMode(RequestMode::No_cors)
- , mCredentialsMode(RequestCredentials::Omit)
- , mResponseTainting(LoadTainting::Basic)
- , mCacheMode(RequestCache::Default)
- , mRedirectMode(RequestRedirect::Follow)
- , mAuthenticationFlag(false)
- , mForceOriginHeader(false)
- , mPreserveContentCodings(false)
- // FIXME(nsm): This should be false by default, but will lead to the
- // algorithm never loading data: URLs right now. See Bug 1018872 about
- // how certain contexts will override it to set it to true. Fetch
- // specification does not handle this yet.
- , mSameOriginDataURL(true)
- , mSkipServiceWorker(false)
- , mSynchronous(false)
- , mUnsafeRequest(false)
- , mUseURLCredentials(false)
- {
- MOZ_ASSERT(!aURL.IsEmpty());
- AddURL(aURL, aFragment);
- }
- InternalRequest::InternalRequest(const nsACString& aURL,
- const nsACString& aFragment,
- const nsACString& aMethod,
- already_AddRefed<InternalHeaders> aHeaders,
- RequestCache aCacheMode,
- RequestMode aMode,
- RequestRedirect aRequestRedirect,
- RequestCredentials aRequestCredentials,
- const nsAString& aReferrer,
- ReferrerPolicy aReferrerPolicy,
- nsContentPolicyType aContentPolicyType,
- const nsAString& aIntegrity)
- : mMethod(aMethod)
- , mHeaders(aHeaders)
- , mContentPolicyType(aContentPolicyType)
- , mReferrer(aReferrer)
- , mReferrerPolicy(aReferrerPolicy)
- , mEnvironmentReferrerPolicy(net::RP_Default)
- , mMode(aMode)
- , mCredentialsMode(aRequestCredentials)
- , mResponseTainting(LoadTainting::Basic)
- , mCacheMode(aCacheMode)
- , mRedirectMode(aRequestRedirect)
- , mIntegrity(aIntegrity)
- , mAuthenticationFlag(false)
- , mForceOriginHeader(false)
- , mPreserveContentCodings(false)
- // FIXME See the above comment in the default constructor.
- , mSameOriginDataURL(true)
- , mSkipServiceWorker(false)
- , mSynchronous(false)
- , mUnsafeRequest(false)
- , mUseURLCredentials(false)
- {
- MOZ_ASSERT(!aURL.IsEmpty());
- AddURL(aURL, aFragment);
- }
- InternalRequest::InternalRequest(const InternalRequest& aOther)
- : mMethod(aOther.mMethod)
- , mURLList(aOther.mURLList)
- , mHeaders(new InternalHeaders(*aOther.mHeaders))
- , mContentPolicyType(aOther.mContentPolicyType)
- , mReferrer(aOther.mReferrer)
- , mReferrerPolicy(aOther.mReferrerPolicy)
- , mEnvironmentReferrerPolicy(aOther.mEnvironmentReferrerPolicy)
- , mMode(aOther.mMode)
- , mCredentialsMode(aOther.mCredentialsMode)
- , mResponseTainting(aOther.mResponseTainting)
- , mCacheMode(aOther.mCacheMode)
- , mRedirectMode(aOther.mRedirectMode)
- , mIntegrity(aOther.mIntegrity)
- , mFragment(aOther.mFragment)
- , mAuthenticationFlag(aOther.mAuthenticationFlag)
- , mForceOriginHeader(aOther.mForceOriginHeader)
- , mPreserveContentCodings(aOther.mPreserveContentCodings)
- , mSameOriginDataURL(aOther.mSameOriginDataURL)
- , mSkipServiceWorker(aOther.mSkipServiceWorker)
- , mSynchronous(aOther.mSynchronous)
- , mUnsafeRequest(aOther.mUnsafeRequest)
- , mUseURLCredentials(aOther.mUseURLCredentials)
- , mCreatedByFetchEvent(aOther.mCreatedByFetchEvent)
- , mContentPolicyTypeOverridden(aOther.mContentPolicyTypeOverridden)
- {
- // NOTE: does not copy body stream... use the fallible Clone() for that
- }
- InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
- : mMethod(aIPCRequest.method())
- , mURLList(aIPCRequest.urls())
- , mHeaders(new InternalHeaders(aIPCRequest.headers(),
- aIPCRequest.headersGuard()))
- , mContentPolicyType(aIPCRequest.contentPolicyType())
- , mReferrer(aIPCRequest.referrer())
- , mReferrerPolicy(aIPCRequest.referrerPolicy())
- , mMode(aIPCRequest.mode())
- , mCredentialsMode(aIPCRequest.credentials())
- , mCacheMode(aIPCRequest.requestCache())
- , mRedirectMode(aIPCRequest.requestRedirect())
- {
- MOZ_ASSERT(!mURLList.IsEmpty());
- }
- InternalRequest::~InternalRequest()
- {
- }
- void
- InternalRequest::ToIPC(IPCInternalRequest* aIPCRequest)
- {
- MOZ_ASSERT(aIPCRequest);
- MOZ_ASSERT(!mURLList.IsEmpty());
- aIPCRequest->urls() = mURLList;
- aIPCRequest->method() = mMethod;
- mHeaders->ToIPC(aIPCRequest->headers(), aIPCRequest->headersGuard());
- aIPCRequest->referrer() = mReferrer;
- aIPCRequest->referrerPolicy() = mReferrerPolicy;
- aIPCRequest->mode() = mMode;
- aIPCRequest->credentials() = mCredentialsMode;
- aIPCRequest->contentPolicyType() = mContentPolicyType;
- aIPCRequest->requestCache() = mCacheMode;
- aIPCRequest->requestRedirect() = mRedirectMode;
- }
- void
- InternalRequest::SetContentPolicyType(nsContentPolicyType aContentPolicyType)
- {
- mContentPolicyType = aContentPolicyType;
- }
- void
- InternalRequest::OverrideContentPolicyType(nsContentPolicyType aContentPolicyType)
- {
- SetContentPolicyType(aContentPolicyType);
- mContentPolicyTypeOverridden = true;
- }
- /* static */
- RequestContext
- InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType)
- {
- RequestContext context = RequestContext::Internal;
- switch (aContentPolicyType) {
- case nsIContentPolicy::TYPE_OTHER:
- context = RequestContext::Internal;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
- case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
- case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
- context = RequestContext::Script;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_WORKER:
- context = RequestContext::Worker;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
- context = RequestContext::Sharedworker;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
- case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
- case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
- context = RequestContext::Image;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
- case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
- context = RequestContext::Style;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
- context = RequestContext::Object;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_EMBED:
- context = RequestContext::Embed;
- break;
- case nsIContentPolicy::TYPE_DOCUMENT:
- context = RequestContext::Internal;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
- context = RequestContext::Iframe;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_FRAME:
- context = RequestContext::Frame;
- break;
- case nsIContentPolicy::TYPE_REFRESH:
- context = RequestContext::Internal;
- break;
- case nsIContentPolicy::TYPE_XBL:
- context = RequestContext::Internal;
- break;
- case nsIContentPolicy::TYPE_PING:
- context = RequestContext::Ping;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST:
- context = RequestContext::Xmlhttprequest;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
- context = RequestContext::Eventsource;
- break;
- case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
- context = RequestContext::Plugin;
- break;
- case nsIContentPolicy::TYPE_DTD:
- context = RequestContext::Internal;
- break;
- case nsIContentPolicy::TYPE_FONT:
- context = RequestContext::Font;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
- context = RequestContext::Audio;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
- context = RequestContext::Video;
- break;
- case nsIContentPolicy::TYPE_INTERNAL_TRACK:
- context = RequestContext::Track;
- break;
- case nsIContentPolicy::TYPE_WEBSOCKET:
- context = RequestContext::Internal;
- break;
- case nsIContentPolicy::TYPE_CSP_REPORT:
- context = RequestContext::Cspreport;
- break;
- case nsIContentPolicy::TYPE_XSLT:
- context = RequestContext::Xslt;
- break;
- case nsIContentPolicy::TYPE_BEACON:
- context = RequestContext::Beacon;
- break;
- case nsIContentPolicy::TYPE_FETCH:
- context = RequestContext::Fetch;
- break;
- case nsIContentPolicy::TYPE_IMAGESET:
- context = RequestContext::Imageset;
- break;
- case nsIContentPolicy::TYPE_WEB_MANIFEST:
- context = RequestContext::Manifest;
- break;
- case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
- context = RequestContext::Internal;
- break;
- default:
- MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
- break;
- }
- return context;
- }
- // static
- bool
- InternalRequest::IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType)
- {
- // 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".
- //
- // Note, all of these request types are effectively initiated by nsDocShell.
- //
- // The TYPE_REFRESH is used in some code paths for metarefresh, but will not
- // be seen during the actual load. Instead the new load gets a normal
- // nsDocShell policy type. We include it here in case this utility method
- // is called before the load starts.
- 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
- InternalRequest::IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType)
- {
- // 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 aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
- aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
- }
- bool
- InternalRequest::IsNavigationRequest() const
- {
- return IsNavigationContentPolicy(mContentPolicyType);
- }
- bool
- InternalRequest::IsWorkerRequest() const
- {
- return IsWorkerContentPolicy(mContentPolicyType);
- }
- bool
- InternalRequest::IsClientRequest() const
- {
- return IsNavigationRequest() || IsWorkerRequest();
- }
- // static
- RequestMode
- InternalRequest::MapChannelToRequestMode(nsIChannel* aChannel)
- {
- MOZ_ASSERT(aChannel);
- nsCOMPtr<nsILoadInfo> loadInfo;
- MOZ_ALWAYS_SUCCEEDS(aChannel->GetLoadInfo(getter_AddRefs(loadInfo)));
- nsContentPolicyType contentPolicy = loadInfo->InternalContentPolicyType();
- if (IsNavigationContentPolicy(contentPolicy)) {
- return RequestMode::Navigate;
- }
- // TODO: remove the worker override once securityMode is fully implemented (bug 1189945)
- if (IsWorkerContentPolicy(contentPolicy)) {
- return RequestMode::Same_origin;
- }
- uint32_t securityMode = loadInfo->GetSecurityMode();
- 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)
- nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(aChannel);
- uint32_t corsMode;
- MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCorsMode(&corsMode));
- MOZ_ASSERT(corsMode != nsIHttpChannelInternal::CORS_MODE_NAVIGATE);
- // This cast is valid due to static asserts in ServiceWorkerManager.cpp.
- return static_cast<RequestMode>(corsMode);
- }
- // static
- RequestCredentials
- InternalRequest::MapChannelToRequestCredentials(nsIChannel* aChannel)
- {
- MOZ_ASSERT(aChannel);
- nsCOMPtr<nsILoadInfo> loadInfo;
- MOZ_ALWAYS_SUCCEEDS(aChannel->GetLoadInfo(getter_AddRefs(loadInfo)));
- // TODO: Remove following code after stylesheet and image support cookie policy
- if (loadInfo->GetSecurityMode() == nsILoadInfo::SEC_NORMAL) {
- uint32_t loadFlags;
- aChannel->GetLoadFlags(&loadFlags);
- if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
- return RequestCredentials::Omit;
- } else {
- bool includeCrossOrigin;
- nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(aChannel);
- internalChannel->GetCorsIncludeCredentials(&includeCrossOrigin);
- if (includeCrossOrigin) {
- return RequestCredentials::Include;
- }
- }
- return RequestCredentials::Same_origin;
- }
- uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
- if (cookiePolicy == nsILoadInfo::SEC_COOKIES_INCLUDE) {
- return RequestCredentials::Include;
- } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) {
- return RequestCredentials::Omit;
- } else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
- return RequestCredentials::Same_origin;
- }
- MOZ_ASSERT_UNREACHABLE("Unexpected cookie policy!");
- return RequestCredentials::Same_origin;
- }
- void
- InternalRequest::MaybeSkipCacheIfPerformingRevalidation()
- {
- if (mCacheMode == RequestCache::Default &&
- mHeaders->HasRevalidationHeaders()) {
- mCacheMode = RequestCache::No_store;
- }
- }
- void
- InternalRequest::SetPrincipalInfo(UniquePtr<mozilla::ipc::PrincipalInfo> aPrincipalInfo)
- {
- mPrincipalInfo = Move(aPrincipalInfo);
- }
- } // namespace dom
- } // namespace mozilla
|