Line data Source code
1 : #include "FetchUtil.h"
2 :
3 : #include "nsError.h"
4 : #include "nsString.h"
5 : #include "nsIDocument.h"
6 :
7 : #include "mozilla/dom/InternalRequest.h"
8 :
9 : namespace mozilla {
10 : namespace dom {
11 :
12 : // static
13 : nsresult
14 3 : FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod)
15 : {
16 6 : nsAutoCString upperCaseMethod(aMethod);
17 3 : ToUpperCase(upperCaseMethod);
18 3 : if (!NS_IsValidHTTPToken(aMethod)) {
19 0 : outMethod.SetIsVoid(true);
20 0 : return NS_ERROR_DOM_SYNTAX_ERR;
21 : }
22 :
23 9 : if (upperCaseMethod.EqualsLiteral("CONNECT") ||
24 6 : upperCaseMethod.EqualsLiteral("TRACE") ||
25 3 : upperCaseMethod.EqualsLiteral("TRACK")) {
26 0 : outMethod.SetIsVoid(true);
27 0 : return NS_ERROR_DOM_SECURITY_ERR;
28 : }
29 :
30 9 : if (upperCaseMethod.EqualsLiteral("DELETE") ||
31 3 : upperCaseMethod.EqualsLiteral("GET") ||
32 0 : upperCaseMethod.EqualsLiteral("HEAD") ||
33 0 : upperCaseMethod.EqualsLiteral("OPTIONS") ||
34 3 : upperCaseMethod.EqualsLiteral("POST") ||
35 0 : upperCaseMethod.EqualsLiteral("PUT")) {
36 3 : outMethod = upperCaseMethod;
37 : }
38 : else {
39 0 : outMethod = aMethod; // Case unchanged for non-standard methods
40 : }
41 3 : return NS_OK;
42 : }
43 :
44 : static bool
45 0 : FindCRLF(nsACString::const_iterator& aStart,
46 : nsACString::const_iterator& aEnd)
47 : {
48 0 : nsACString::const_iterator end(aEnd);
49 0 : return FindInReadable(NS_LITERAL_CSTRING("\r\n"), aStart, end);
50 : }
51 :
52 : // Reads over a CRLF and positions start after it.
53 : static bool
54 0 : PushOverLine(nsACString::const_iterator& aStart,
55 : const nsACString::const_iterator& aEnd)
56 : {
57 0 : if (*aStart == nsCRT::CR && (aEnd - aStart > 1) && *(++aStart) == nsCRT::LF) {
58 0 : ++aStart; // advance to after CRLF
59 0 : return true;
60 : }
61 :
62 0 : return false;
63 : }
64 :
65 : // static
66 : bool
67 0 : FetchUtil::ExtractHeader(nsACString::const_iterator& aStart,
68 : nsACString::const_iterator& aEnd,
69 : nsCString& aHeaderName,
70 : nsCString& aHeaderValue,
71 : bool* aWasEmptyHeader)
72 : {
73 0 : MOZ_ASSERT(aWasEmptyHeader);
74 : // Set it to a valid value here so we don't forget later.
75 0 : *aWasEmptyHeader = false;
76 :
77 0 : const char* beginning = aStart.get();
78 0 : nsACString::const_iterator end(aEnd);
79 0 : if (!FindCRLF(aStart, end)) {
80 0 : return false;
81 : }
82 :
83 0 : if (aStart.get() == beginning) {
84 0 : *aWasEmptyHeader = true;
85 0 : return true;
86 : }
87 :
88 0 : nsAutoCString header(beginning, aStart.get() - beginning);
89 :
90 0 : nsACString::const_iterator headerStart, iter, headerEnd;
91 0 : header.BeginReading(headerStart);
92 0 : header.EndReading(headerEnd);
93 0 : iter = headerStart;
94 0 : if (!FindCharInReadable(':', iter, headerEnd)) {
95 0 : return false;
96 : }
97 :
98 0 : aHeaderName.Assign(StringHead(header, iter - headerStart));
99 0 : aHeaderName.CompressWhitespace();
100 0 : if (!NS_IsValidHTTPToken(aHeaderName)) {
101 0 : return false;
102 : }
103 :
104 0 : aHeaderValue.Assign(Substring(++iter, headerEnd));
105 0 : if (!NS_IsReasonableHTTPHeaderValue(aHeaderValue)) {
106 0 : return false;
107 : }
108 0 : aHeaderValue.CompressWhitespace();
109 :
110 0 : return PushOverLine(aStart, aEnd);
111 : }
112 :
113 : // static
114 : nsresult
115 0 : FetchUtil::SetRequestReferrer(nsIPrincipal* aPrincipal,
116 : nsIDocument* aDoc,
117 : nsIHttpChannel* aChannel,
118 : InternalRequest* aRequest) {
119 0 : MOZ_ASSERT(NS_IsMainThread());
120 :
121 0 : nsAutoString referrer;
122 0 : aRequest->GetReferrer(referrer);
123 0 : net::ReferrerPolicy policy = aRequest->GetReferrerPolicy();
124 :
125 0 : nsresult rv = NS_OK;
126 0 : if (referrer.IsEmpty()) {
127 : // This is the case request’s referrer is "no-referrer"
128 0 : rv = aChannel->SetReferrerWithPolicy(nullptr, net::RP_No_Referrer);
129 0 : NS_ENSURE_SUCCESS(rv, rv);
130 0 : } else if (referrer.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
131 : rv = nsContentUtils::SetFetchReferrerURIWithPolicy(aPrincipal,
132 : aDoc,
133 : aChannel,
134 0 : policy);
135 0 : NS_ENSURE_SUCCESS(rv, rv);
136 : } else {
137 : // From "Determine request's Referrer" step 3
138 : // "If request's referrer is a URL, let referrerSource be request's
139 : // referrer."
140 0 : nsCOMPtr<nsIURI> referrerURI;
141 0 : rv = NS_NewURI(getter_AddRefs(referrerURI), referrer, nullptr, nullptr);
142 0 : NS_ENSURE_SUCCESS(rv, rv);
143 :
144 0 : rv = aChannel->SetReferrerWithPolicy(referrerURI, policy);
145 0 : NS_ENSURE_SUCCESS(rv, rv);
146 : }
147 :
148 0 : nsCOMPtr<nsIURI> referrerURI;
149 0 : Unused << aChannel->GetReferrer(getter_AddRefs(referrerURI));
150 :
151 : // Step 8 https://fetch.spec.whatwg.org/#main-fetch
152 : // If request’s referrer is not "no-referrer", set request’s referrer to
153 : // the result of invoking determine request’s referrer.
154 0 : if (referrerURI) {
155 0 : nsAutoCString spec;
156 0 : rv = referrerURI->GetSpec(spec);
157 0 : NS_ENSURE_SUCCESS(rv, rv);
158 :
159 0 : aRequest->SetReferrer(NS_ConvertUTF8toUTF16(spec));
160 : } else {
161 0 : aRequest->SetReferrer(EmptyString());
162 : }
163 :
164 0 : return NS_OK;
165 : }
166 :
167 : } // namespace dom
168 : } // namespace mozilla
|