2 * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
4 * Copyright (C) 2010 Google Inc. All Rights Reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "core/html/parser/CSSPreloadScanner.h"
31 #include "core/fetch/FetchInitiatorTypeNames.h"
32 #include "core/html/parser/HTMLParserIdioms.h"
33 #include "platform/text/SegmentedString.h"
37 CSSPreloadScanner::CSSPreloadScanner()
40 , m_referrerPolicy(ReferrerPolicyDefault
)
44 CSSPreloadScanner::~CSSPreloadScanner()
48 void CSSPreloadScanner::reset()
55 template<typename Char
>
56 void CSSPreloadScanner::scanCommon(const Char
* begin
, const Char
* end
, const SegmentedString
& source
, PreloadRequestStream
& requests
)
58 m_requests
= &requests
;
59 for (const Char
* it
= begin
; it
!= end
&& m_state
!= DoneParsingImportRules
; ++it
)
60 tokenize(*it
, source
);
64 void CSSPreloadScanner::scan(const HTMLToken::DataVector
& data
, const SegmentedString
& source
, PreloadRequestStream
& requests
)
66 scanCommon(data
.data(), data
.data() + data
.size(), source
, requests
);
69 void CSSPreloadScanner::scan(const String
& tagName
, const SegmentedString
& source
, PreloadRequestStream
& requests
)
71 if (tagName
.is8Bit()) {
72 const LChar
* begin
= tagName
.characters8();
73 scanCommon(begin
, begin
+ tagName
.length(), source
, requests
);
76 const UChar
* begin
= tagName
.characters16();
77 scanCommon(begin
, begin
+ tagName
.length(), source
, requests
);
80 void CSSPreloadScanner::setReferrerPolicy(const ReferrerPolicy policy
)
82 m_referrerPolicy
= policy
;
85 inline void CSSPreloadScanner::tokenize(UChar c
, const SegmentedString
& source
)
87 // We are just interested in @import rules, no need for real tokenization here
88 // Searching for other types of resources is probably low payoff.
91 if (isHTMLSpace
<UChar
>(c
))
96 m_state
= MaybeComment
;
98 m_state
= DoneParsingImportRules
;
108 m_state
= MaybeCommentEnd
;
110 case MaybeCommentEnd
:
119 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')) {
128 if (isHTMLSpace
<UChar
>(c
))
136 if (isHTMLSpace
<UChar
>(c
))
141 m_state
= DoneParsingImportRules
;
144 m_ruleValue
.append(c
);
148 if (isHTMLSpace
<UChar
>(c
))
149 m_state
= AfterRuleValue
;
153 m_ruleValue
.append(c
);
156 if (isHTMLSpace
<UChar
>(c
))
161 m_state
= DoneParsingImportRules
;
163 // FIXME: media rules
167 case DoneParsingImportRules
:
168 ASSERT_NOT_REACHED();
173 static String
parseCSSStringOrURL(const String
& string
)
176 size_t reducedLength
= string
.length();
178 while (reducedLength
&& isHTMLSpace
<UChar
>(string
[offset
])) {
182 while (reducedLength
&& isHTMLSpace
<UChar
>(string
[offset
+ reducedLength
- 1]))
185 if (reducedLength
>= 5
186 && (string
[offset
] == 'u' || string
[offset
] == 'U')
187 && (string
[offset
+ 1] == 'r' || string
[offset
+ 1] == 'R')
188 && (string
[offset
+ 2] == 'l' || string
[offset
+ 2] == 'L')
189 && string
[offset
+ 3] == '('
190 && string
[offset
+ reducedLength
- 1] == ')') {
195 while (reducedLength
&& isHTMLSpace
<UChar
>(string
[offset
])) {
199 while (reducedLength
&& isHTMLSpace
<UChar
>(string
[offset
+ reducedLength
- 1]))
202 if (reducedLength
< 2 || string
[offset
] != string
[offset
+ reducedLength
- 1] || !(string
[offset
] == '\'' || string
[offset
] == '"'))
207 while (reducedLength
&& isHTMLSpace
<UChar
>(string
[offset
])) {
211 while (reducedLength
&& isHTMLSpace
<UChar
>(string
[offset
+ reducedLength
- 1]))
214 return string
.substring(offset
, reducedLength
);
217 void CSSPreloadScanner::emitRule(const SegmentedString
& source
)
219 if (equalIgnoringCase(m_rule
, "import")) {
220 String url
= parseCSSStringOrURL(m_ruleValue
.toString());
221 if (!url
.isEmpty()) {
222 KURL baseElementURL
; // FIXME: This should be passed in from the HTMLPreloadScaner via scan()!
223 TextPosition position
= TextPosition(source
.currentLine(), source
.currentColumn());
224 OwnPtr
<PreloadRequest
> request
= PreloadRequest::create(FetchInitiatorTypeNames::css
, position
, url
, baseElementURL
, Resource::CSSStyleSheet
, m_referrerPolicy
);
225 // FIXME: Should this be including the charset in the preload request?
226 m_requests
->append(request
.release());
229 } else if (equalIgnoringCase(m_rule
, "charset"))
232 m_state
= DoneParsingImportRules
;