2015-09-11 21:26:33 +03:00
|
|
|
|
#include "FetchUtil.h"
|
2015-09-17 15:10:42 +03:00
|
|
|
|
|
2015-09-11 21:26:33 +03:00
|
|
|
|
#include "nsError.h"
|
2015-09-17 15:10:42 +03:00
|
|
|
|
#include "nsIUnicodeDecoder.h"
|
2015-09-11 21:26:33 +03:00
|
|
|
|
#include "nsString.h"
|
2016-11-14 10:15:32 +03:00
|
|
|
|
#include "nsIDocument.h"
|
2015-09-11 21:26:33 +03:00
|
|
|
|
|
2015-09-17 15:10:42 +03:00
|
|
|
|
#include "mozilla/dom/EncodingUtils.h"
|
2016-11-14 10:15:32 +03:00
|
|
|
|
#include "mozilla/dom/InternalRequest.h"
|
2015-09-17 15:10:42 +03:00
|
|
|
|
|
2015-09-11 21:26:33 +03:00
|
|
|
|
namespace mozilla {
|
|
|
|
|
namespace dom {
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
nsresult
|
|
|
|
|
FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod)
|
|
|
|
|
{
|
|
|
|
|
nsAutoCString upperCaseMethod(aMethod);
|
|
|
|
|
ToUpperCase(upperCaseMethod);
|
2016-03-17 10:29:42 +03:00
|
|
|
|
if (!NS_IsValidHTTPToken(aMethod)) {
|
|
|
|
|
outMethod.SetIsVoid(true);
|
|
|
|
|
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-11 21:26:33 +03:00
|
|
|
|
if (upperCaseMethod.EqualsLiteral("CONNECT") ||
|
|
|
|
|
upperCaseMethod.EqualsLiteral("TRACE") ||
|
2016-03-17 10:29:42 +03:00
|
|
|
|
upperCaseMethod.EqualsLiteral("TRACK")) {
|
2015-09-11 21:26:33 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-25 00:42:35 +03:00
|
|
|
|
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
|
2016-09-30 05:33:57 +03:00
|
|
|
|
PushOverLine(nsACString::const_iterator& aStart,
|
|
|
|
|
const nsACString::const_iterator& aEnd)
|
2015-10-25 00:42:35 +03:00
|
|
|
|
{
|
2016-09-30 05:33:57 +03:00
|
|
|
|
if (*aStart == nsCRT::CR && (aEnd - aStart > 1) && *(++aStart) == nsCRT::LF) {
|
2015-10-25 00:42:35 +03:00
|
|
|
|
++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);
|
|
|
|
|
|
2016-09-30 05:33:57 +03:00
|
|
|
|
nsACString::const_iterator headerStart, iter, headerEnd;
|
2015-10-25 00:42:35 +03:00
|
|
|
|
header.BeginReading(headerStart);
|
|
|
|
|
header.EndReading(headerEnd);
|
2016-09-30 05:33:57 +03:00
|
|
|
|
iter = headerStart;
|
|
|
|
|
if (!FindCharInReadable(':', iter, headerEnd)) {
|
2015-10-25 00:42:35 +03:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-30 05:33:57 +03:00
|
|
|
|
aHeaderName.Assign(StringHead(header, iter - headerStart));
|
2015-10-25 00:42:35 +03:00
|
|
|
|
aHeaderName.CompressWhitespace();
|
|
|
|
|
if (!NS_IsValidHTTPToken(aHeaderName)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-30 05:33:57 +03:00
|
|
|
|
aHeaderValue.Assign(Substring(++iter, headerEnd));
|
2015-10-25 00:42:35 +03:00
|
|
|
|
if (!NS_IsReasonableHTTPHeaderValue(aHeaderValue)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
aHeaderValue.CompressWhitespace();
|
|
|
|
|
|
2016-09-30 05:33:57 +03:00
|
|
|
|
return PushOverLine(aStart, aEnd);
|
2015-10-25 00:42:35 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-14 10:15:32 +03:00
|
|
|
|
// 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 request’s 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;
|
|
|
|
|
aChannel->GetReferrer(getter_AddRefs(referrerURI));
|
|
|
|
|
|
|
|
|
|
// Step 8 https://fetch.spec.whatwg.org/#main-fetch
|
|
|
|
|
// If request’s referrer is not "no-referrer", set request’s referrer to
|
|
|
|
|
// the result of invoking determine request’s 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;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-11 21:26:33 +03:00
|
|
|
|
} // namespace dom
|
|
|
|
|
} // namespace mozilla
|