| 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 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 #include "config.h" | 28 #include "config.h" |
| 29 #include "HTMLPreloadScanner.h" | 29 #include "HTMLPreloadScanner.h" |
| 30 | 30 |
| 31 #include "HTMLNames.h" | 31 #include "HTMLNames.h" |
| 32 #include "HTMLParserIdioms.h" | 32 #include "HTMLParserIdioms.h" |
| 33 #include "HTMLParserOptions.h" | 33 #include "HTMLParserOptions.h" |
| 34 #include "HTMLTokenizer.h" | 34 #include "HTMLTokenizer.h" |
| 35 #include "InputTypeNames.h" | 35 #include "InputTypeNames.h" |
| 36 #include "LinkRelAttribute.h" | 36 #include "LinkRelAttribute.h" |
| 37 #include "MediaList.h" | |
| 38 #include "MediaQueryEvaluator.h" | |
| 39 #include <wtf/Functional.h> | 37 #include <wtf/Functional.h> |
| 40 #include <wtf/MainThread.h> | 38 #include <wtf/MainThread.h> |
| 41 | 39 |
| 42 namespace WebCore { | 40 namespace WebCore { |
| 43 | 41 |
| 44 using namespace HTMLNames; | 42 using namespace HTMLNames; |
| 45 | 43 |
| 46 TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const HTMLToken::DataVe
ctor& data) | 44 TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const HTMLToken::DataVe
ctor& data) |
| 47 { | 45 { |
| 48 AtomicString tagName(data); | 46 AtomicString tagName(data); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 102 } |
| 105 ASSERT_NOT_REACHED(); | 103 ASSERT_NOT_REACHED(); |
| 106 return "unknown"; | 104 return "unknown"; |
| 107 } | 105 } |
| 108 | 106 |
| 109 class TokenPreloadScanner::StartTagScanner { | 107 class TokenPreloadScanner::StartTagScanner { |
| 110 public: | 108 public: |
| 111 explicit StartTagScanner(TagId tagId) | 109 explicit StartTagScanner(TagId tagId) |
| 112 : m_tagId(tagId) | 110 : m_tagId(tagId) |
| 113 , m_linkIsStyleSheet(false) | 111 , m_linkIsStyleSheet(false) |
| 114 , m_linkMediaAttributeIsScreen(true) | |
| 115 , m_inputIsImage(false) | 112 , m_inputIsImage(false) |
| 116 { | 113 { |
| 117 } | 114 } |
| 118 | 115 |
| 119 void processAttributes(const HTMLToken::AttributeList& attributes) | 116 void processAttributes(const HTMLToken::AttributeList& attributes) |
| 120 { | 117 { |
| 121 ASSERT(isMainThread()); | 118 ASSERT(isMainThread()); |
| 122 if (m_tagId >= UnknownTagId) | 119 if (m_tagId >= UnknownTagId) |
| 123 return; | 120 return; |
| 124 for (HTMLToken::AttributeList::const_iterator iter = attributes.begin();
iter != attributes.end(); ++iter) { | 121 for (HTMLToken::AttributeList::const_iterator iter = attributes.begin();
iter != attributes.end(); ++iter) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 136 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut
es.begin(); iter != attributes.end(); ++iter) | 133 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut
es.begin(); iter != attributes.end(); ++iter) |
| 137 processAttribute(iter->name, iter->value); | 134 processAttribute(iter->name, iter->value); |
| 138 } | 135 } |
| 139 #endif | 136 #endif |
| 140 | 137 |
| 141 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL
) | 138 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL
) |
| 142 { | 139 { |
| 143 if (!shouldPreload()) | 140 if (!shouldPreload()) |
| 144 return nullptr; | 141 return nullptr; |
| 145 | 142 |
| 146 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t
agId), m_urlToLoad, predictedBaseURL, resourceType()); | 143 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t
agId), m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribute); |
| 147 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies())
; | 144 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies())
; |
| 148 request->setCharset(charset()); | 145 request->setCharset(charset()); |
| 149 return request.release(); | 146 return request.release(); |
| 150 } | 147 } |
| 151 | 148 |
| 152 static bool match(const AtomicString& name, const QualifiedName& qName) | 149 static bool match(const AtomicString& name, const QualifiedName& qName) |
| 153 { | 150 { |
| 154 ASSERT(isMainThread()); | 151 ASSERT(isMainThread()); |
| 155 return qName.localName() == name; | 152 return qName.localName() == name; |
| 156 } | 153 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 173 if (match(attributeName, srcAttr)) | 170 if (match(attributeName, srcAttr)) |
| 174 setUrlToLoad(attributeValue); | 171 setUrlToLoad(attributeValue); |
| 175 else if (match(attributeName, crossoriginAttr) && !attributeValue.is
Null()) | 172 else if (match(attributeName, crossoriginAttr) && !attributeValue.is
Null()) |
| 176 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV
alue); | 173 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV
alue); |
| 177 } else if (m_tagId == LinkTagId) { | 174 } else if (m_tagId == LinkTagId) { |
| 178 if (match(attributeName, hrefAttr)) | 175 if (match(attributeName, hrefAttr)) |
| 179 setUrlToLoad(attributeValue); | 176 setUrlToLoad(attributeValue); |
| 180 else if (match(attributeName, relAttr)) | 177 else if (match(attributeName, relAttr)) |
| 181 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); | 178 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); |
| 182 else if (match(attributeName, mediaAttr)) | 179 else if (match(attributeName, mediaAttr)) |
| 183 m_linkMediaAttributeIsScreen = linkMediaAttributeIsScreen(attrib
uteValue); | 180 m_mediaAttribute = attributeValue; |
| 184 } else if (m_tagId == InputTagId) { | 181 } else if (m_tagId == InputTagId) { |
| 185 if (match(attributeName, srcAttr)) | 182 if (match(attributeName, srcAttr)) |
| 186 setUrlToLoad(attributeValue); | 183 setUrlToLoad(attributeValue); |
| 187 else if (match(attributeName, typeAttr)) | 184 else if (match(attributeName, typeAttr)) |
| 188 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName
s::image()); | 185 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName
s::image()); |
| 189 } | 186 } |
| 190 } | 187 } |
| 191 | 188 |
| 192 static bool relAttributeIsStyleSheet(const String& attributeValue) | 189 static bool relAttributeIsStyleSheet(const String& attributeValue) |
| 193 { | 190 { |
| 194 LinkRelAttribute rel(attributeValue); | 191 LinkRelAttribute rel(attributeValue); |
| 195 return rel.m_isStyleSheet && !rel.m_isAlternate && rel.m_iconType == Inv
alidIcon && !rel.m_isDNSPrefetch; | 192 return rel.m_isStyleSheet && !rel.m_isAlternate && rel.m_iconType == Inv
alidIcon && !rel.m_isDNSPrefetch; |
| 196 } | 193 } |
| 197 | 194 |
| 198 static bool linkMediaAttributeIsScreen(const String& attributeValue) | |
| 199 { | |
| 200 if (attributeValue.isEmpty()) | |
| 201 return true; | |
| 202 RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::createAllowingDescri
ptionSyntax(attributeValue); | |
| 203 | |
| 204 // Only preload screen media stylesheets. Used this way, the evaluator e
valuates to true for any | |
| 205 // rules containing complex queries (full evaluation is possible but it
requires a frame and a style selector which | |
| 206 // may be problematic here). | |
| 207 MediaQueryEvaluator mediaQueryEvaluator("screen"); | |
| 208 return mediaQueryEvaluator.eval(mediaQueries.get()); | |
| 209 } | |
| 210 | |
| 211 void setUrlToLoad(const String& attributeValue) | 195 void setUrlToLoad(const String& attributeValue) |
| 212 { | 196 { |
| 213 // We only respect the first src/href, per HTML5: | 197 // We only respect the first src/href, per HTML5: |
| 214 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenizat
ion.html#attribute-name-state | 198 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenizat
ion.html#attribute-name-state |
| 215 if (!m_urlToLoad.isEmpty()) | 199 if (!m_urlToLoad.isEmpty()) |
| 216 return; | 200 return; |
| 217 m_urlToLoad = stripLeadingAndTrailingHTMLSpaces(attributeValue); | 201 m_urlToLoad = stripLeadingAndTrailingHTMLSpaces(attributeValue); |
| 218 } | 202 } |
| 219 | 203 |
| 220 const String& charset() const | 204 const String& charset() const |
| 221 { | 205 { |
| 222 // FIXME: Its not clear that this if is needed, the loader probably igno
res charset for image requests anyway. | 206 // FIXME: Its not clear that this if is needed, the loader probably igno
res charset for image requests anyway. |
| 223 if (m_tagId == ImgTagId) | 207 if (m_tagId == ImgTagId) |
| 224 return emptyString(); | 208 return emptyString(); |
| 225 return m_charset; | 209 return m_charset; |
| 226 } | 210 } |
| 227 | 211 |
| 228 CachedResource::Type resourceType() const | 212 CachedResource::Type resourceType() const |
| 229 { | 213 { |
| 230 if (m_tagId == ScriptTagId) | 214 if (m_tagId == ScriptTagId) |
| 231 return CachedResource::Script; | 215 return CachedResource::Script; |
| 232 if (m_tagId == ImgTagId || (m_tagId == InputTagId && m_inputIsImage)) | 216 if (m_tagId == ImgTagId || (m_tagId == InputTagId && m_inputIsImage)) |
| 233 return CachedResource::ImageResource; | 217 return CachedResource::ImageResource; |
| 234 if (m_tagId == LinkTagId && m_linkIsStyleSheet && m_linkMediaAttributeIs
Screen) | 218 if (m_tagId == LinkTagId && m_linkIsStyleSheet) |
| 235 return CachedResource::CSSStyleSheet; | 219 return CachedResource::CSSStyleSheet; |
| 236 ASSERT_NOT_REACHED(); | 220 ASSERT_NOT_REACHED(); |
| 237 return CachedResource::RawResource; | 221 return CachedResource::RawResource; |
| 238 } | 222 } |
| 239 | 223 |
| 240 bool shouldPreload() | 224 bool shouldPreload() |
| 241 { | 225 { |
| 242 if (m_urlToLoad.isEmpty()) | 226 if (m_urlToLoad.isEmpty()) |
| 243 return false; | 227 return false; |
| 244 | 228 |
| 245 if (m_tagId == LinkTagId && (!m_linkIsStyleSheet || !m_linkMediaAttribut
eIsScreen)) | 229 if (m_tagId == LinkTagId && !m_linkIsStyleSheet) |
| 246 return false; | 230 return false; |
| 247 | 231 |
| 248 if (m_tagId == InputTagId && !m_inputIsImage) | 232 if (m_tagId == InputTagId && !m_inputIsImage) |
| 249 return false; | 233 return false; |
| 250 | 234 |
| 251 return true; | 235 return true; |
| 252 } | 236 } |
| 253 | 237 |
| 254 bool crossOriginModeAllowsCookies() | 238 bool crossOriginModeAllowsCookies() |
| 255 { | 239 { |
| 256 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode
, "use-credentials"); | 240 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode
, "use-credentials"); |
| 257 } | 241 } |
| 258 | 242 |
| 259 TagId m_tagId; | 243 TagId m_tagId; |
| 260 String m_urlToLoad; | 244 String m_urlToLoad; |
| 261 String m_charset; | 245 String m_charset; |
| 262 String m_crossOriginMode; | 246 String m_crossOriginMode; |
| 263 bool m_linkIsStyleSheet; | 247 bool m_linkIsStyleSheet; |
| 264 bool m_linkMediaAttributeIsScreen; | 248 String m_mediaAttribute; |
| 265 bool m_inputIsImage; | 249 bool m_inputIsImage; |
| 266 }; | 250 }; |
| 267 | 251 |
| 268 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL) | 252 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL) |
| 269 : m_documentURL(documentURL) | 253 : m_documentURL(documentURL) |
| 270 , m_inStyle(false) | 254 , m_inStyle(false) |
| 271 , m_templateCount(0) | 255 , m_templateCount(0) |
| 272 { | 256 { |
| 273 } | 257 } |
| 274 | 258 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 if (m_token.type() == HTMLToken::StartTag) | 384 if (m_token.type() == HTMLToken::StartTag) |
| 401 m_tokenizer->updateStateFor(AtomicString(m_token.name())); | 385 m_tokenizer->updateStateFor(AtomicString(m_token.name())); |
| 402 m_scanner.scan(m_token, requests); | 386 m_scanner.scan(m_token, requests); |
| 403 m_token.clear(); | 387 m_token.clear(); |
| 404 } | 388 } |
| 405 | 389 |
| 406 preloader->takeAndPreload(requests); | 390 preloader->takeAndPreload(requests); |
| 407 } | 391 } |
| 408 | 392 |
| 409 } | 393 } |
| OLD | NEW |