gecko-dev/dom/fetch/InternalRequest.h
Ehsan Akhgari 47c59f235a Bug 1147699 - Part 1: Move Request::mContext to InternalRequest, and determine the mapping to nsContentPolicyType; r=nsm
As the documentation in InternalRequest.h in this patch shows, the
mapping between nsContentPolicyType and RequestContext is not complete
yet.  Because the InternalRequest object needs to know the actual
nsContentPolicyType in order for FetchDriver to be able to use that
information, we can't just store the RequestContext.  Therefore, this
patch adds both of these to InternalRequest.  Once we get to a stage
where we have a complete mapping of these values, we can store only one
of them and compute the other from it.  That requires addressing all of
the TODO comments in the InternalRequest.h documentation.
2015-03-30 08:42:31 -04:00

415 lines
9.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; 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/. */
#ifndef mozilla_dom_InternalRequest_h
#define mozilla_dom_InternalRequest_h
#include "mozilla/dom/HeadersBinding.h"
#include "mozilla/dom/InternalHeaders.h"
#include "mozilla/dom/RequestBinding.h"
#include "nsIContentPolicy.h"
#include "nsIInputStream.h"
#include "nsISupportsImpl.h"
#ifdef DEBUG
#include "nsIURLParser.h"
#include "nsNetCID.h"
#include "nsServiceManagerUtils.h"
#endif
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
/*
* The mapping of RequestContext and nsContentPolicyType is currently as the
* following. Note that this mapping is not perfect yet (see the TODO comments
* below for examples), so for now we'll have to keep both an mContext and an
* mContentPolicyType, because we cannot have a two way conversion.
*
* RequestContext | nsContentPolicyType
* ------------------+--------------------
* audio | TYPE_MEDIA
* beacon | TYPE_BEACON
* cspreport | TYPE_CSP_REPORT
* download |
* embed | TYPE_OBJECT
* eventsource |
* favicon |
* fetch | TYPE_FETCH
* font | TYPE_FONT
* form |
* frame | TYPE_SUBDOCUMENT
* hyperlink |
* iframe | TYPE_SUBDOCUMENT
* image | TYPE_IMAGE
* imageset | TYPE_IMAGESET
* import | Not supported by Gecko
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
* location |
* manifest |
* object | TYPE_OBJECT
* ping | TYPE_PING
* plugin | TYPE_OBJECT_SUBREQUEST
* prefetch |
* script | TYPE_SCRIPT
* serviceworker |
* sharedworker |
* subresource | Not supported by Gecko
* style | TYPE_STYLESHEET
* track | TYPE_MEDIA
* video | TYPE_MEDIA
* worker |
* xmlhttprequest | TYPE_XMLHTTPREQUEST
* xslt | TYPE_XSLT
*
* TODO: Figure out if TYPE_REFRESH maps to anything useful
* TODO: Figure out if TYPE_DTD maps to anything useful
* TODO: Split TYPE_MEDIA into TYPE_AUDIO, TYPE_VIDEO and TYPE_TRACK
* TODO: Split TYPE_XMLHTTPREQUEST and TYPE_DATAREQUEST for EventSource
* TODO: Figure out if TYPE_WEBSOCKET maps to anything useful
* TODO: Differentiate between frame and iframe
* TODO: Add content types for different kinds of workers
* TODO: Add a content type for prefetch
* TODO: Use the content type for manifest when it becomes available
* TODO: Add a content type for location
* TODO: Add a content type for hyperlink
* TODO: Add a content type for form
* TODO: Add a content type for favicon
* TODO: Add a content type for download
* TODO: Split TYPE_OBJECT into TYPE_EMBED and TYPE_OBJECT
*/
class FetchBodyStream;
class Request;
#define kFETCH_CLIENT_REFERRER_STR "about:client"
class InternalRequest final
{
friend class Request;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalRequest)
enum ResponseTainting
{
RESPONSETAINT_BASIC,
RESPONSETAINT_CORS,
RESPONSETAINT_OPAQUE,
};
explicit InternalRequest()
: mMethod("GET")
, mHeaders(new InternalHeaders(HeadersGuardEnum::None))
, mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
, mMode(RequestMode::No_cors)
, mCredentialsMode(RequestCredentials::Omit)
, mResponseTainting(RESPONSETAINT_BASIC)
, mCacheMode(RequestCache::Default)
, 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)
{
}
already_AddRefed<InternalRequest> Clone();
void
GetMethod(nsCString& aMethod) const
{
aMethod.Assign(mMethod);
}
void
SetMethod(const nsACString& aMethod)
{
mMethod.Assign(aMethod);
}
bool
HasSimpleMethod() const
{
return mMethod.LowerCaseEqualsASCII("get") ||
mMethod.LowerCaseEqualsASCII("post") ||
mMethod.LowerCaseEqualsASCII("head");
}
void
GetURL(nsCString& aURL) const
{
aURL.Assign(mURL);
}
void
SetURL(const nsACString& aURL)
{
mURL.Assign(aURL);
}
void
GetReferrer(nsAString& aReferrer) const
{
aReferrer.Assign(mReferrer);
}
void
SetReferrer(const nsAString& aReferrer)
{
#ifdef DEBUG
bool validReferrer = false;
if (aReferrer.IsEmpty() ||
aReferrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
validReferrer = true;
} else {
nsCOMPtr<nsIURLParser> parser = do_GetService(NS_STDURLPARSER_CONTRACTID);
if (!parser) {
NS_WARNING("Could not get parser to validate URL!");
} else {
uint32_t schemePos;
int32_t schemeLen;
uint32_t authorityPos;
int32_t authorityLen;
uint32_t pathPos;
int32_t pathLen;
NS_ConvertUTF16toUTF8 ref(aReferrer);
nsresult rv = parser->ParseURL(ref.get(), ref.Length(),
&schemePos, &schemeLen,
&authorityPos, &authorityLen,
&pathPos, &pathLen);
if (NS_FAILED(rv)) {
NS_WARNING("Invalid referrer URL!");
} else if (schemeLen < 0 || authorityLen < 0) {
NS_WARNING("Invalid referrer URL!");
} else {
validReferrer = true;
}
}
}
MOZ_ASSERT(validReferrer);
#endif
mReferrer.Assign(aReferrer);
}
bool
SkipServiceWorker() const
{
return mSkipServiceWorker;
}
void
SetSkipServiceWorker()
{
mSkipServiceWorker = true;
}
bool
IsSynchronous() const
{
return mSynchronous;
}
RequestMode
Mode() const
{
return mMode;
}
void
SetMode(RequestMode aMode)
{
mMode = aMode;
}
RequestCredentials
GetCredentialsMode() const
{
return mCredentialsMode;
}
void
SetCredentialsMode(RequestCredentials aCredentialsMode)
{
mCredentialsMode = aCredentialsMode;
}
ResponseTainting
GetResponseTainting() const
{
return mResponseTainting;
}
void
SetResponseTainting(ResponseTainting aTainting)
{
mResponseTainting = aTainting;
}
RequestCache
GetCacheMode() const
{
return mCacheMode;
}
void
SetCacheMode(RequestCache aCacheMode)
{
mCacheMode = aCacheMode;
}
nsContentPolicyType
ContentPolicyType() const
{
return mContentPolicyType;
}
void
SetContentPolicyType(nsContentPolicyType aContentPolicyType);
RequestContext
Context() const
{
return mContext;
}
void
SetContext(RequestContext aContext)
{
mContext = aContext;
}
bool
UnsafeRequest() const
{
return mUnsafeRequest;
}
void
SetUnsafeRequest()
{
mUnsafeRequest = true;
}
InternalHeaders*
Headers()
{
return mHeaders;
}
bool
ForceOriginHeader()
{
return mForceOriginHeader;
}
bool
SameOriginDataURL() const
{
return mSameOriginDataURL;
}
void
UnsetSameOriginDataURL()
{
mSameOriginDataURL = false;
}
void
SetBody(nsIInputStream* aStream)
{
// A request's body may not be reset once set.
MOZ_ASSERT(!mBodyStream);
mBodyStream = aStream;
}
// Will return the original stream!
// Use a tee or copy if you don't want to erase the original.
void
GetBody(nsIInputStream** aStream)
{
nsCOMPtr<nsIInputStream> s = mBodyStream;
s.forget(aStream);
}
// The global is used as the client for the new object.
already_AddRefed<InternalRequest>
GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const;
bool
WasCreatedByFetchEvent() const
{
return mCreatedByFetchEvent;
}
void
SetCreatedByFetchEvent()
{
mCreatedByFetchEvent = true;
}
void
ClearCreatedByFetchEvent()
{
mCreatedByFetchEvent = false;
}
private:
// Does not copy mBodyStream. Use fallible Clone() for complete copy.
explicit InternalRequest(const InternalRequest& aOther);
~InternalRequest();
nsCString mMethod;
nsCString mURL;
nsRefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBodyStream;
nsContentPolicyType mContentPolicyType;
RequestContext mContext;
// Empty string: no-referrer
// "about:client": client (default)
// URL: an URL
nsString mReferrer;
RequestMode mMode;
RequestCredentials mCredentialsMode;
ResponseTainting mResponseTainting;
RequestCache mCacheMode;
bool mAuthenticationFlag;
bool mForceOriginHeader;
bool mPreserveContentCodings;
bool mSameOriginDataURL;
bool mSandboxedStorageAreaURLs;
bool mSkipServiceWorker;
bool mSynchronous;
bool mUnsafeRequest;
bool mUseURLCredentials;
// This is only set when a Request object is created by a fetch event. We
// use it to check if Service Workers are simply fetching intercepted Request
// objects without modifying them.
bool mCreatedByFetchEvent = false;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_InternalRequest_h