Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: third_party/WebKit/Source/core/loader/LinkHeader.cpp

Issue 1811163002: Share link header parsing code between blink and content. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@base-optional
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/loader/LinkHeader.h"
6
7 #include "platform/ParsingUtilities.h"
8
9 namespace blink {
10
11 // LWSP definition in https://www.ietf.org/rfc/rfc0822.txt
12 template <typename CharType>
13 static bool isWhitespace(CharType chr)
14 {
15 return (chr == ' ') || (chr == '\t');
16 }
17
18 template <typename CharType>
19 static bool isValidURLChar(CharType chr)
20 {
21 return !isWhitespace(chr) && chr != '>';
22 }
23
24 template <typename CharType>
25 static bool isValidParameterNameChar(CharType chr)
26 {
27 // TODO(yoav): We need to move this function to a central location and possi bly rewrite as a lookup table. https://crbug.com/527324
28
29 // Alpha-numeric is a valid char.
30 // This is likely the common case - bailing early.
31 if (isASCIIAlphanumeric(chr))
32 return true;
33 // A separator or CTL or '%', '*' or '\'' means the char is not valid.
34 // So any of: |{}[]/\:;<=>?@,()*'"%
35 if (chr <= ' ' || chr > '|' || chr == '{' || chr == ']' || chr == '['
36 || chr == '/' || chr == '\\' || (chr <= '@' && chr >= ':') || chr == ','
37 || (chr >= '(' && chr <= '*') || chr == '\'' || chr == '"' || chr == '%' ) {
38 return false;
39 }
40 return true;
41 }
42
43 template <typename CharType>
44 static bool isValidParameterValueEnd(CharType chr)
45 {
46 return chr == ';' || chr == ',';
47 }
48
49 template <typename CharType>
50 static bool isValidParameterValueChar(CharType chr)
51 {
52 return !isWhitespace(chr) && !isValidParameterValueEnd(chr);
53 }
54
55 // Verify that the parameter is a link-extension which according to spec doesn't have to have a value.
56 static bool isExtensionParameter(LinkHeader::LinkParameterName name)
57 {
58 return name >= LinkHeader::LinkParameterUnknown;
59 }
60
61 // Before:
62 //
63 // <cat.jpg>; rel=preload
64 // ^ ^
65 // position end
66 //
67 // After (if successful: otherwise the method returns false)
68 //
69 // <cat.jpg>; rel=preload
70 // ^ ^
71 // position end
72 template <typename CharType>
73 static bool parseURL(CharType*& position, CharType* end, String& url)
74 {
75 skipWhile<CharType, isWhitespace>(position, end);
76 if (!skipExactly<CharType>(position, end, '<'))
77 return false;
78 skipWhile<CharType, isWhitespace>(position, end);
79
80 CharType* urlStart = position;
81 skipWhile<CharType, isValidURLChar>(position, end);
82 CharType* urlEnd = position;
83 skipUntil<CharType>(position, end, '>');
84 if (!skipExactly<CharType>(position, end, '>'))
85 return false;
86
87 url = String(urlStart, urlEnd - urlStart);
88 return true;
89 }
90
91 template <typename CharType>
92 static bool invalidParameterDelimiter(CharType*& position, CharType* end)
93 {
94 return (!skipExactly<CharType>(position, end, ';') && (position < end) && (* position != ','));
95 }
96
97 template <typename CharType>
98 static bool validFieldEnd(CharType*& position, CharType* end)
99 {
100 ASSERT(position <= end);
101 return (position == end || *position == ',');
102 }
103
104 // Before:
105 //
106 // <cat.jpg>; rel=preload
107 // ^ ^
108 // position end
109 //
110 // After (if successful: otherwise the method returns false, and modifies the is Valid boolean accordingly)
111 //
112 // <cat.jpg>; rel=preload
113 // ^ ^
114 // position end
115 template <typename CharType>
116 static bool parseParameterDelimiter(CharType*& position, CharType* end, bool& is Valid)
117 {
118 isValid = true;
119 skipWhile<CharType, isWhitespace>(position, end);
120 if (invalidParameterDelimiter(position, end)) {
121 isValid = false;
122 return false;
123 }
124 skipWhile<CharType, isWhitespace>(position, end);
125 if (validFieldEnd(position, end))
126 return false;
127 return true;
128 }
129
130 static LinkHeader::LinkParameterName paramterNameFromString(String name)
131 {
132 if (equalIgnoringCase(name, "rel"))
133 return LinkHeader::LinkParameterRel;
134 if (equalIgnoringCase(name, "anchor"))
135 return LinkHeader::LinkParameterAnchor;
136 if (equalIgnoringCase(name, "crossorigin"))
137 return LinkHeader::LinkParameterCrossOrigin;
138 if (equalIgnoringCase(name, "title"))
139 return LinkHeader::LinkParameterTitle;
140 if (equalIgnoringCase(name, "media"))
141 return LinkHeader::LinkParameterMedia;
142 if (equalIgnoringCase(name, "type"))
143 return LinkHeader::LinkParameterType;
144 if (equalIgnoringCase(name, "rev"))
145 return LinkHeader::LinkParameterRev;
146 if (equalIgnoringCase(name, "hreflang"))
147 return LinkHeader::LinkParameterHreflang;
148 if (equalIgnoringCase(name, "as"))
149 return LinkHeader::LinkParameterAs;
150 return LinkHeader::LinkParameterUnknown;
151 }
152
153 // Before:
154 //
155 // <cat.jpg>; rel=preload
156 // ^ ^
157 // position end
158 //
159 // After (if successful: otherwise the method returns false)
160 //
161 // <cat.jpg>; rel=preload
162 // ^ ^
163 // position end
164 template <typename CharType>
165 static bool parseParameterName(CharType*& position, CharType* end, LinkHeader::L inkParameterName& name)
166 {
167 CharType* nameStart = position;
168 skipWhile<CharType, isValidParameterNameChar>(position, end);
169 CharType* nameEnd = position;
170 skipWhile<CharType, isWhitespace>(position, end);
171 bool hasEqual = skipExactly<CharType>(position, end, '=');
172 skipWhile<CharType, isWhitespace>(position, end);
173 name = paramterNameFromString(String(nameStart, nameEnd - nameStart));
174 if (hasEqual)
175 return true;
176 bool validParameterValueEnd = (position == end) || isValidParameterValueEnd( *position);
177 return validParameterValueEnd && isExtensionParameter(name);
178 }
179
180 // Before:
181 //
182 // <cat.jpg>; rel="preload"; type="image/jpeg";
183 // ^ ^
184 // position end
185 //
186 // After (if the parameter starts with a quote, otherwise the method returns fal se)
187 //
188 // <cat.jpg>; rel="preload"; type="image/jpeg";
189 // ^ ^
190 // position end
191 template <typename CharType>
192 static bool skipQuotesIfNeeded(CharType*& position, CharType* end, bool& complet eQuotes)
193 {
194 ASSERT(position <= end);
195 unsigned char quote;
196 completeQuotes = false;
197 if (skipExactly<CharType>(position, end, '\''))
198 quote = '\'';
199 else if (skipExactly<CharType>(position, end, '"'))
200 quote = '"';
201 else
202 return false;
203
204 while (!completeQuotes && position < end) {
205 skipUntil(position, end, static_cast<CharType>(quote));
206 if (*(position - 1) != '\\')
207 completeQuotes = true;
208 completeQuotes = skipExactly(position, end, static_cast<CharType>(quote) ) && completeQuotes;
209 }
210 return true;
211 }
212
213 // Before:
214 //
215 // <cat.jpg>; rel=preload; foo=bar
216 // ^ ^
217 // position end
218 //
219 // After (if successful: otherwise the method returns false)
220 //
221 // <cat.jpg>; rel=preload; foo=bar
222 // ^ ^
223 // position end
224 template <typename CharType>
225 static bool parseParameterValue(CharType*& position, CharType* end, String& valu e)
226 {
227 CharType* valueStart = position;
228 CharType* valueEnd = position;
229 bool completeQuotes;
230 bool hasQuotes = skipQuotesIfNeeded(position, end, completeQuotes);
231 if (!hasQuotes) {
232 skipWhile<CharType, isValidParameterValueChar>(position, end);
233 }
234 valueEnd = position;
235 skipWhile<CharType, isWhitespace>(position, end);
236 if ((!completeQuotes && valueStart == valueEnd) || (position != end && !isVa lidParameterValueEnd(*position))) {
237 value = String("");
238 return false;
239 }
240 if (hasQuotes)
241 ++valueStart;
242 if (completeQuotes)
243 --valueEnd;
244 value = String(valueStart, valueEnd - valueStart);
245 return !hasQuotes || completeQuotes;
246 }
247
248 void LinkHeader::setValue(LinkParameterName name, String value)
249 {
250 // FIXME: Add support for more header parameters as neccessary.
251 if (name == LinkParameterRel && !m_rel)
252 m_rel = value.lower();
253 else if (name == LinkParameterAnchor)
254 m_isValid = false;
255 else if (name == LinkParameterCrossOrigin)
256 m_crossOrigin = crossOriginAttributeValue(value);
257 else if (name == LinkParameterAs)
258 m_as = value.lower();
259 else if (name == LinkParameterType)
260 m_mimeType = value.lower();
261 else if (name == LinkParameterMedia)
262 m_media = value.lower();
263 }
264
265 template <typename CharType>
266 static void findNextHeader(CharType*& position, CharType* end)
267 {
268 skipUntil<CharType>(position, end, ',');
269 skipExactly<CharType>(position, end, ',');
270 }
271
272 template <typename CharType>
273 LinkHeader::LinkHeader(CharType*& position, CharType* end)
274 : m_crossOrigin(CrossOriginAttributeNotSet)
275 , m_isValid(true)
276 {
277 if (!parseURL(position, end, m_url)) {
278 m_isValid = false;
279 findNextHeader(position, end);
280 return;
281 }
282
283 while (m_isValid && position < end) {
284 if (!parseParameterDelimiter(position, end, m_isValid)) {
285 findNextHeader(position, end);
286 return;
287 }
288
289 LinkParameterName parameterName;
290 if (!parseParameterName(position, end, parameterName)) {
291 findNextHeader(position, end);
292 m_isValid = false;
293 return;
294 }
295
296 String parameterValue;
297 if (!parseParameterValue(position, end, parameterValue) && !isExtensionP arameter(parameterName)) {
298 findNextHeader(position, end);
299 m_isValid = false;
300 return;
301 }
302
303 setValue(parameterName, parameterValue);
304 }
305 findNextHeader(position, end);
306 }
307
308 LinkHeaderSet::LinkHeaderSet(const String& header)
309 {
310 if (header.isNull())
311 return;
312
313 if (header.is8Bit())
314 init(header.characters8(), header.length());
315 else
316 init(header.characters16(), header.length());
317 }
318
319 template <typename CharType>
320 void LinkHeaderSet::init(CharType* headerValue, unsigned len)
321 {
322 CharType* position = headerValue;
323 CharType* end = headerValue + len;
324 while (position < end)
325 m_headerSet.append(LinkHeader(position, end));
326 }
327
328 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698