OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ | 3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ |
4 * Copyright (C) 2010 Google Inc. All Rights Reserved. | 4 * Copyright (C) 2010 Google Inc. All Rights Reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 11 matching lines...) Expand all Loading... |
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include "config.h" | 28 #include "config.h" |
29 #include "core/html/parser/HTMLPreloadScanner.h" | 29 #include "core/html/parser/HTMLPreloadScanner.h" |
30 | 30 |
31 #include "HTMLNames.h" | 31 #include "HTMLNames.h" |
| 32 #include "core/css/MediaList.h" |
| 33 #include "core/css/MediaQueryEvaluator.h" |
32 #include "core/html/InputTypeNames.h" | 34 #include "core/html/InputTypeNames.h" |
33 #include "core/html/LinkRelAttribute.h" | 35 #include "core/html/LinkRelAttribute.h" |
34 #include "core/html/parser/HTMLParserIdioms.h" | 36 #include "core/html/parser/HTMLParserIdioms.h" |
35 #include "core/html/parser/HTMLTokenizer.h" | 37 #include "core/html/parser/HTMLTokenizer.h" |
36 #include "wtf/MainThread.h" | 38 #include "wtf/MainThread.h" |
37 | |
38 namespace WebCore { | 39 namespace WebCore { |
39 | 40 |
40 using namespace HTMLNames; | 41 using namespace HTMLNames; |
41 | 42 |
42 static bool match(const StringImpl* impl, const QualifiedName& qName) | 43 static bool match(const StringImpl* impl, const QualifiedName& qName) |
43 { | 44 { |
44 return impl == qName.localName().impl(); | 45 return impl == qName.localName().impl(); |
45 } | 46 } |
46 | 47 |
47 static bool match(const HTMLIdentifier& name, const QualifiedName& qName) | 48 static bool match(const HTMLIdentifier& name, const QualifiedName& qName) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 if (match(tagImpl, inputTag)) | 81 if (match(tagImpl, inputTag)) |
81 return inputTag.localName(); | 82 return inputTag.localName(); |
82 if (match(tagImpl, linkTag)) | 83 if (match(tagImpl, linkTag)) |
83 return linkTag.localName(); | 84 return linkTag.localName(); |
84 if (match(tagImpl, scriptTag)) | 85 if (match(tagImpl, scriptTag)) |
85 return scriptTag.localName(); | 86 return scriptTag.localName(); |
86 ASSERT_NOT_REACHED(); | 87 ASSERT_NOT_REACHED(); |
87 return "unknown"; | 88 return "unknown"; |
88 } | 89 } |
89 | 90 |
| 91 static bool mediaAttributeMatches(const MediaValues* mediaValues, const String&
attributeValue) |
| 92 { |
| 93 RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(attributeValue); |
| 94 MediaQueryEvaluator mediaQueryEvaluator("screen", mediaValues, false); |
| 95 bool ret = mediaQueryEvaluator.eval(mediaQueries.get()); |
| 96 return ret; |
| 97 } |
| 98 |
90 class TokenPreloadScanner::StartTagScanner { | 99 class TokenPreloadScanner::StartTagScanner { |
91 public: | 100 public: |
92 explicit StartTagScanner(const StringImpl* tagImpl) | 101 explicit StartTagScanner(const StringImpl* tagImpl, PassRefPtr<MediaValues>
mediaValues) |
93 : m_tagImpl(tagImpl) | 102 : m_tagImpl(tagImpl) |
94 , m_linkIsStyleSheet(false) | 103 , m_linkIsStyleSheet(false) |
95 , m_inputIsImage(false) | 104 , m_inputIsImage(false) |
| 105 , m_mediaMatch(true) |
| 106 , m_mediaValues(MediaValues::copy(mediaValues.get())) |
96 { | 107 { |
97 if (!match(m_tagImpl, imgTag) | 108 if (!match(m_tagImpl, imgTag) |
98 && !match(m_tagImpl, inputTag) | 109 && !match(m_tagImpl, inputTag) |
99 && !match(m_tagImpl, linkTag) | 110 && !match(m_tagImpl, linkTag) |
100 && !match(m_tagImpl, scriptTag)) | 111 && !match(m_tagImpl, scriptTag)) |
101 m_tagImpl = 0; | 112 m_tagImpl = 0; |
102 } | 113 } |
103 | 114 |
104 void processAttributes(const HTMLToken::AttributeList& attributes) | 115 void processAttributes(const HTMLToken::AttributeList& attributes) |
105 { | 116 { |
(...skipping 10 matching lines...) Expand all Loading... |
116 void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes
) | 127 void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes
) |
117 { | 128 { |
118 if (!m_tagImpl) | 129 if (!m_tagImpl) |
119 return; | 130 return; |
120 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut
es.begin(); iter != attributes.end(); ++iter) | 131 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut
es.begin(); iter != attributes.end(); ++iter) |
121 processAttribute(iter->name, iter->value); | 132 processAttribute(iter->name, iter->value); |
122 } | 133 } |
123 | 134 |
124 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL
, const SegmentedString& source) | 135 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL
, const SegmentedString& source) |
125 { | 136 { |
126 if (!shouldPreload()) | 137 if (!shouldPreload() || !m_mediaMatch) |
127 return nullptr; | 138 return nullptr; |
128 | 139 |
129 TextPosition position = TextPosition(source.currentLine(), source.curren
tColumn()); | 140 TextPosition position = TextPosition(source.currentLine(), source.curren
tColumn()); |
130 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t
agImpl), position, m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribu
te); | 141 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t
agImpl), position, m_urlToLoad, predictedBaseURL, resourceType()); |
131 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies())
; | 142 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies())
; |
132 request->setCharset(charset()); | 143 request->setCharset(charset()); |
133 return request.release(); | 144 return request.release(); |
134 } | 145 } |
135 | 146 |
136 private: | 147 private: |
| 148 |
137 template<typename NameType> | 149 template<typename NameType> |
138 void processAttribute(const NameType& attributeName, const String& attribute
Value) | 150 void processAttribute(const NameType& attributeName, const String& attribute
Value) |
139 { | 151 { |
140 if (match(attributeName, charsetAttr)) | 152 if (match(attributeName, charsetAttr)) |
141 m_charset = attributeValue; | 153 m_charset = attributeValue; |
142 | 154 |
143 if (match(m_tagImpl, scriptTag) || match(m_tagImpl, imgTag)) { | 155 if (match(m_tagImpl, scriptTag) || match(m_tagImpl, imgTag)) { |
144 if (match(attributeName, srcAttr)) | 156 if (match(attributeName, srcAttr)) |
145 setUrlToLoad(attributeValue); | 157 setUrlToLoad(attributeValue); |
146 else if (match(attributeName, crossoriginAttr) && !attributeValue.is
Null()) | 158 else if (match(attributeName, crossoriginAttr) && !attributeValue.is
Null()) |
147 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV
alue); | 159 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV
alue); |
148 } else if (match(m_tagImpl, linkTag)) { | 160 } else if (match(m_tagImpl, linkTag)) { |
149 if (match(attributeName, hrefAttr)) | 161 if (match(attributeName, hrefAttr)) |
150 setUrlToLoad(attributeValue); | 162 setUrlToLoad(attributeValue); |
151 else if (match(attributeName, relAttr)) | 163 else if (match(attributeName, relAttr)) |
152 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); | 164 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); |
153 else if (match(attributeName, mediaAttr)) | 165 else if (match(attributeName, mediaAttr)) |
154 m_mediaAttribute = attributeValue; | 166 m_mediaMatch = mediaAttributeMatches(m_mediaValues.get(), attrib
uteValue); |
155 } else if (match(m_tagImpl, inputTag)) { | 167 } else if (match(m_tagImpl, inputTag)) { |
156 if (match(attributeName, srcAttr)) | 168 if (match(attributeName, srcAttr)) |
157 setUrlToLoad(attributeValue); | 169 setUrlToLoad(attributeValue); |
158 else if (match(attributeName, typeAttr)) | 170 else if (match(attributeName, typeAttr)) |
159 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName
s::image()); | 171 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName
s::image()); |
160 } | 172 } |
161 } | 173 } |
162 | 174 |
163 static bool relAttributeIsStyleSheet(const String& attributeValue) | 175 static bool relAttributeIsStyleSheet(const String& attributeValue) |
164 { | 176 { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 bool crossOriginModeAllowsCookies() | 221 bool crossOriginModeAllowsCookies() |
210 { | 222 { |
211 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode
, "use-credentials"); | 223 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode
, "use-credentials"); |
212 } | 224 } |
213 | 225 |
214 const StringImpl* m_tagImpl; | 226 const StringImpl* m_tagImpl; |
215 String m_urlToLoad; | 227 String m_urlToLoad; |
216 String m_charset; | 228 String m_charset; |
217 String m_crossOriginMode; | 229 String m_crossOriginMode; |
218 bool m_linkIsStyleSheet; | 230 bool m_linkIsStyleSheet; |
219 String m_mediaAttribute; | 231 bool m_mediaMatch; |
220 bool m_inputIsImage; | 232 bool m_inputIsImage; |
| 233 RefPtr<MediaValues> m_mediaValues; |
221 }; | 234 }; |
222 | 235 |
223 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL) | 236 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL, PassRefPtr<Med
iaValues> mediaValues) |
224 : m_documentURL(documentURL) | 237 : m_documentURL(documentURL) |
225 , m_inStyle(false) | 238 , m_inStyle(false) |
226 , m_templateCount(0) | 239 , m_templateCount(0) |
| 240 , m_mediaValues(mediaValues) |
227 { | 241 { |
228 } | 242 } |
229 | 243 |
230 TokenPreloadScanner::~TokenPreloadScanner() | 244 TokenPreloadScanner::~TokenPreloadScanner() |
231 { | 245 { |
232 } | 246 } |
233 | 247 |
234 TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint() | 248 TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint() |
235 { | 249 { |
236 TokenPreloadScannerCheckpoint checkpoint = m_checkpoints.size(); | 250 TokenPreloadScannerCheckpoint checkpoint = m_checkpoints.size(); |
237 m_checkpoints.append(Checkpoint(m_predictedBaseElementURL, m_inStyle, m_temp
lateCount)); | 251 m_checkpoints.append(Checkpoint(m_predictedBaseElementURL, m_inStyle, m_temp
lateCount)); |
238 return checkpoint; | 252 return checkpoint; |
239 } | 253 } |
240 | 254 |
| 255 |
241 void TokenPreloadScanner::rewindTo(TokenPreloadScannerCheckpoint checkpointIndex
) | 256 void TokenPreloadScanner::rewindTo(TokenPreloadScannerCheckpoint checkpointIndex
) |
242 { | 257 { |
243 ASSERT(checkpointIndex < m_checkpoints.size()); // If this ASSERT fires, che
ckpointIndex is invalid. | 258 ASSERT(checkpointIndex < m_checkpoints.size()); // If this ASSERT fires, che
ckpointIndex is invalid. |
244 const Checkpoint& checkpoint = m_checkpoints[checkpointIndex]; | 259 const Checkpoint& checkpoint = m_checkpoints[checkpointIndex]; |
245 m_predictedBaseElementURL = checkpoint.predictedBaseElementURL; | 260 m_predictedBaseElementURL = checkpoint.predictedBaseElementURL; |
246 m_inStyle = checkpoint.inStyle; | 261 m_inStyle = checkpoint.inStyle; |
247 m_templateCount = checkpoint.templateCount; | 262 m_templateCount = checkpoint.templateCount; |
248 m_cssScanner.reset(); | 263 m_cssScanner.reset(); |
249 m_checkpoints.clear(); | 264 m_checkpoints.clear(); |
250 } | 265 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 return; | 311 return; |
297 } | 312 } |
298 if (match(tagImpl, baseTag)) { | 313 if (match(tagImpl, baseTag)) { |
299 // The first <base> element is the one that wins. | 314 // The first <base> element is the one that wins. |
300 if (!m_predictedBaseElementURL.isEmpty()) | 315 if (!m_predictedBaseElementURL.isEmpty()) |
301 return; | 316 return; |
302 updatePredictedBaseURL(token); | 317 updatePredictedBaseURL(token); |
303 return; | 318 return; |
304 } | 319 } |
305 | 320 |
306 StartTagScanner scanner(tagImpl); | 321 StartTagScanner scanner(tagImpl, m_mediaValues); |
307 scanner.processAttributes(token.attributes()); | 322 scanner.processAttributes(token.attributes()); |
308 OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predicte
dBaseElementURL, source); | 323 OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predicte
dBaseElementURL, source); |
309 if (request) | 324 if (request) |
310 requests.append(request.release()); | 325 requests.append(request.release()); |
311 return; | 326 return; |
312 } | 327 } |
313 default: { | 328 default: { |
314 return; | 329 return; |
315 } | 330 } |
316 } | 331 } |
317 } | 332 } |
318 | 333 |
319 template<typename Token> | 334 template<typename Token> |
320 void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) | 335 void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) |
321 { | 336 { |
322 ASSERT(m_predictedBaseElementURL.isEmpty()); | 337 ASSERT(m_predictedBaseElementURL.isEmpty()); |
323 if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem(
hrefAttr)) | 338 if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem(
hrefAttr)) |
324 m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingH
TMLSpaces(hrefAttribute->value)).copy(); | 339 m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingH
TMLSpaces(hrefAttribute->value)).copy(); |
325 } | 340 } |
326 | 341 |
327 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const K
URL& documentURL) | 342 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const K
URL& documentURL, PassRefPtr<MediaValues> mediaValues) |
328 : m_scanner(documentURL) | 343 : m_scanner(documentURL, mediaValues) |
329 , m_tokenizer(HTMLTokenizer::create(options)) | 344 , m_tokenizer(HTMLTokenizer::create(options)) |
330 { | 345 { |
331 } | 346 } |
332 | 347 |
333 HTMLPreloadScanner::~HTMLPreloadScanner() | 348 HTMLPreloadScanner::~HTMLPreloadScanner() |
334 { | 349 { |
335 } | 350 } |
336 | 351 |
337 void HTMLPreloadScanner::appendToEnd(const SegmentedString& source) | 352 void HTMLPreloadScanner::appendToEnd(const SegmentedString& source) |
338 { | 353 { |
(...skipping 14 matching lines...) Expand all Loading... |
353 if (m_token.type() == HTMLToken::StartTag) | 368 if (m_token.type() == HTMLToken::StartTag) |
354 m_tokenizer->updateStateFor(AtomicString(m_token.name())); | 369 m_tokenizer->updateStateFor(AtomicString(m_token.name())); |
355 m_scanner.scan(m_token, m_source, requests); | 370 m_scanner.scan(m_token, m_source, requests); |
356 m_token.clear(); | 371 m_token.clear(); |
357 } | 372 } |
358 | 373 |
359 preloader->takeAndPreload(requests); | 374 preloader->takeAndPreload(requests); |
360 } | 375 } |
361 | 376 |
362 } | 377 } |
OLD | NEW |