gecko-dev/dom/fetch/FetchUtil.cpp
2017-06-13 13:23:23 +03:00

169 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "FetchUtil.h"
#include "nsError.h"
#include "nsString.h"
#include "nsIDocument.h"
#include "mozilla/dom/InternalRequest.h"
namespace mozilla {
namespace dom {
// static
nsresult
FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod)
{
nsAutoCString upperCaseMethod(aMethod);
ToUpperCase(upperCaseMethod);
if (!NS_IsValidHTTPToken(aMethod)) {
outMethod.SetIsVoid(true);
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (upperCaseMethod.EqualsLiteral("CONNECT") ||
upperCaseMethod.EqualsLiteral("TRACE") ||
upperCaseMethod.EqualsLiteral("TRACK")) {
outMethod.SetIsVoid(true);
return NS_ERROR_DOM_SECURITY_ERR;
}
if (upperCaseMethod.EqualsLiteral("DELETE") ||
upperCaseMethod.EqualsLiteral("GET") ||
upperCaseMethod.EqualsLiteral("HEAD") ||
upperCaseMethod.EqualsLiteral("OPTIONS") ||
upperCaseMethod.EqualsLiteral("POST") ||
upperCaseMethod.EqualsLiteral("PUT")) {
outMethod = upperCaseMethod;
}
else {
outMethod = aMethod; // Case unchanged for non-standard methods
}
return NS_OK;
}
static bool
FindCRLF(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
nsACString::const_iterator end(aEnd);
return FindInReadable(NS_LITERAL_CSTRING("\r\n"), aStart, end);
}
// Reads over a CRLF and positions start after it.
static bool
PushOverLine(nsACString::const_iterator& aStart,
const nsACString::const_iterator& aEnd)
{
if (*aStart == nsCRT::CR && (aEnd - aStart > 1) && *(++aStart) == nsCRT::LF) {
++aStart; // advance to after CRLF
return true;
}
return false;
}
// static
bool
FetchUtil::ExtractHeader(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd,
nsCString& aHeaderName,
nsCString& aHeaderValue,
bool* aWasEmptyHeader)
{
MOZ_ASSERT(aWasEmptyHeader);
// Set it to a valid value here so we don't forget later.
*aWasEmptyHeader = false;
const char* beginning = aStart.get();
nsACString::const_iterator end(aEnd);
if (!FindCRLF(aStart, end)) {
return false;
}
if (aStart.get() == beginning) {
*aWasEmptyHeader = true;
return true;
}
nsAutoCString header(beginning, aStart.get() - beginning);
nsACString::const_iterator headerStart, iter, headerEnd;
header.BeginReading(headerStart);
header.EndReading(headerEnd);
iter = headerStart;
if (!FindCharInReadable(':', iter, headerEnd)) {
return false;
}
aHeaderName.Assign(StringHead(header, iter - headerStart));
aHeaderName.CompressWhitespace();
if (!NS_IsValidHTTPToken(aHeaderName)) {
return false;
}
aHeaderValue.Assign(Substring(++iter, headerEnd));
if (!NS_IsReasonableHTTPHeaderValue(aHeaderValue)) {
return false;
}
aHeaderValue.CompressWhitespace();
return PushOverLine(aStart, aEnd);
}
// static
nsresult
FetchUtil::SetRequestReferrer(nsIPrincipal* aPrincipal,
nsIDocument* aDoc,
nsIHttpChannel* aChannel,
InternalRequest* aRequest) {
MOZ_ASSERT(NS_IsMainThread());
nsAutoString referrer;
aRequest->GetReferrer(referrer);
net::ReferrerPolicy policy = aRequest->GetReferrerPolicy();
nsresult rv = NS_OK;
if (referrer.IsEmpty()) {
// This is the case requests referrer is "no-referrer"
rv = aChannel->SetReferrerWithPolicy(nullptr, net::RP_No_Referrer);
NS_ENSURE_SUCCESS(rv, rv);
} else if (referrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
rv = nsContentUtils::SetFetchReferrerURIWithPolicy(aPrincipal,
aDoc,
aChannel,
policy);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// From "Determine request's Referrer" step 3
// "If request's referrer is a URL, let referrerSource be request's
// referrer."
nsCOMPtr<nsIURI> referrerURI;
rv = NS_NewURI(getter_AddRefs(referrerURI), referrer, nullptr, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
rv = aChannel->SetReferrerWithPolicy(referrerURI, policy);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIURI> referrerURI;
Unused << aChannel->GetReferrer(getter_AddRefs(referrerURI));
// Step 8 https://fetch.spec.whatwg.org/#main-fetch
// If requests referrer is not "no-referrer", set requests referrer to
// the result of invoking determine requests referrer.
if (referrerURI) {
nsAutoCString spec;
rv = referrerURI->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
aRequest->SetReferrer(NS_ConvertUTF8toUTF16(spec));
} else {
aRequest->SetReferrer(EmptyString());
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla