Chromium Code Reviews| 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 "RuntimeEnabledFeatures.h" | |
| 32 #include "core/html/InputTypeNames.h" | 33 #include "core/html/InputTypeNames.h" |
| 33 #include "core/html/LinkRelAttribute.h" | 34 #include "core/html/LinkRelAttribute.h" |
| 34 #include "core/html/parser/HTMLParserIdioms.h" | 35 #include "core/html/parser/HTMLParserIdioms.h" |
| 36 #include "core/html/parser/HTMLSrcsetParser.h" | |
| 35 #include "core/html/parser/HTMLTokenizer.h" | 37 #include "core/html/parser/HTMLTokenizer.h" |
| 36 #include "core/platform/chromium/TraceEvent.h" | 38 #include "core/platform/chromium/TraceEvent.h" |
| 37 #include "wtf/MainThread.h" | 39 #include "wtf/MainThread.h" |
| 38 | 40 |
| 39 namespace WebCore { | 41 namespace WebCore { |
| 40 | 42 |
| 41 using namespace HTMLNames; | 43 using namespace HTMLNames; |
| 42 | 44 |
| 43 static bool match(const StringImpl* impl, const QualifiedName& qName) | 45 static bool match(const StringImpl* impl, const QualifiedName& qName) |
| 44 { | 46 { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 if (match(tagImpl, linkTag)) | 85 if (match(tagImpl, linkTag)) |
| 84 return linkTag.localName(); | 86 return linkTag.localName(); |
| 85 if (match(tagImpl, scriptTag)) | 87 if (match(tagImpl, scriptTag)) |
| 86 return scriptTag.localName(); | 88 return scriptTag.localName(); |
| 87 ASSERT_NOT_REACHED(); | 89 ASSERT_NOT_REACHED(); |
| 88 return emptyString(); | 90 return emptyString(); |
| 89 } | 91 } |
| 90 | 92 |
| 91 class TokenPreloadScanner::StartTagScanner { | 93 class TokenPreloadScanner::StartTagScanner { |
| 92 public: | 94 public: |
| 93 explicit StartTagScanner(const StringImpl* tagImpl) | 95 explicit StartTagScanner(const StringImpl* tagImpl, float deviceScaleFactor) |
| 94 : m_tagImpl(tagImpl) | 96 : m_tagImpl(tagImpl) |
| 95 , m_linkIsStyleSheet(false) | 97 , m_linkIsStyleSheet(false) |
| 96 , m_inputIsImage(false) | 98 , m_inputIsImage(false) |
| 99 , m_deviceScaleFactor(deviceScaleFactor) | |
| 97 { | 100 { |
| 98 if (!match(m_tagImpl, imgTag) | 101 if (!match(m_tagImpl, imgTag) |
| 99 && !match(m_tagImpl, inputTag) | 102 && !match(m_tagImpl, inputTag) |
| 100 && !match(m_tagImpl, linkTag) | 103 && !match(m_tagImpl, linkTag) |
| 101 && !match(m_tagImpl, scriptTag)) | 104 && !match(m_tagImpl, scriptTag)) |
| 102 m_tagImpl = 0; | 105 m_tagImpl = 0; |
| 103 } | 106 } |
| 104 | 107 |
| 108 enum URLReplacement { URLReplacementAllow, URLReplacementDisallow }; | |
|
abarth-chromium
2013/09/13 22:24:06
Each of these should be on its own line.
| |
| 109 | |
| 110 | |
|
abarth-chromium
2013/09/13 22:24:06
Please remove this extra blank line.
| |
| 111 void applySrcset() | |
| 112 { | |
| 113 // Resolve between src and srcSet if we have them. | |
|
abarth-chromium
2013/09/13 22:24:06
This "what" comment isn't needed. Please remove i
| |
| 114 if (RuntimeEnabledFeatures::srcsetEnabled() && match(m_tagImpl, imgTag) && !m_srcSetAttribute.isEmpty()) | |
| 115 setUrlToLoad(bestFitSourceForImageAttributes(m_deviceScaleFactor, m_ urlToLoad, m_srcSetAttribute), URLReplacementAllow); | |
| 116 } | |
| 117 | |
| 105 void processAttributes(const HTMLToken::AttributeList& attributes) | 118 void processAttributes(const HTMLToken::AttributeList& attributes) |
| 106 { | 119 { |
| 107 ASSERT(isMainThread()); | 120 ASSERT(isMainThread()); |
| 108 if (!m_tagImpl) | 121 if (!m_tagImpl) |
| 109 return; | 122 return; |
| 110 for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { | 123 for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { |
| 111 AtomicString attributeName(iter->name); | 124 AtomicString attributeName(iter->name); |
| 112 String attributeValue = StringImpl::create8BitIfPossible(iter->value ); | 125 String attributeValue = StringImpl::create8BitIfPossible(iter->value ); |
| 113 processAttribute(attributeName, attributeValue); | 126 processAttribute(attributeName, attributeValue); |
| 114 } | 127 } |
| 128 | |
| 129 applySrcset(); | |
|
abarth-chromium
2013/09/13 22:24:06
As I wrote before, we don't want to do any srcset
| |
| 115 } | 130 } |
| 116 | 131 |
| 117 void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes ) | 132 void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes ) |
| 118 { | 133 { |
| 119 if (!m_tagImpl) | 134 if (!m_tagImpl) |
| 120 return; | 135 return; |
| 121 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut es.begin(); iter != attributes.end(); ++iter) | 136 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut es.begin(); iter != attributes.end(); ++iter) |
| 122 processAttribute(iter->name, iter->value); | 137 processAttribute(iter->name, iter->value); |
| 138 | |
| 139 applySrcset(); | |
| 123 } | 140 } |
| 124 | 141 |
| 125 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL , const SegmentedString& source) | 142 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL , const SegmentedString& source) |
| 126 { | 143 { |
| 127 if (!shouldPreload()) | 144 if (!shouldPreload()) |
| 128 return nullptr; | 145 return nullptr; |
| 129 | 146 |
| 130 TRACE_EVENT_INSTANT1("net", "PreloadRequest", "url", m_urlToLoad.ascii() ); | 147 TRACE_EVENT_INSTANT1("net", "PreloadRequest", "url", m_urlToLoad.ascii() ); |
| 131 TextPosition position = TextPosition(source.currentLine(), source.curren tColumn()); | 148 TextPosition position = TextPosition(source.currentLine(), source.curren tColumn()); |
| 132 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t agImpl), position, m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribu te); | 149 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t agImpl), position, m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribu te); |
| 133 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies()) ; | 150 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies()) ; |
| 134 request->setCharset(charset()); | 151 request->setCharset(charset()); |
| 135 return request.release(); | 152 return request.release(); |
| 136 } | 153 } |
| 137 | 154 |
| 138 private: | 155 private: |
| 139 template<typename NameType> | 156 template<typename NameType> |
| 140 void processAttribute(const NameType& attributeName, const String& attribute Value) | 157 void processAttribute(const NameType& attributeName, const String& attribute Value) |
| 141 { | 158 { |
| 142 if (match(attributeName, charsetAttr)) | 159 if (match(attributeName, charsetAttr)) |
| 143 m_charset = attributeValue; | 160 m_charset = attributeValue; |
| 144 | 161 |
| 145 if (match(m_tagImpl, scriptTag) || match(m_tagImpl, imgTag)) { | 162 if (match(m_tagImpl, scriptTag) || match(m_tagImpl, imgTag)) { |
| 146 if (match(attributeName, srcAttr)) | 163 if (match(attributeName, srcAttr)) |
| 147 setUrlToLoad(attributeValue); | 164 setUrlToLoad(attributeValue, URLReplacementDisallow); |
|
abarth-chromium
2013/09/13 22:24:06
URLReplacementDisallow -> DisallowURLReplacement
| |
| 148 else if (match(attributeName, crossoriginAttr) && !attributeValue.is Null()) | 165 else if (match(attributeName, crossoriginAttr) && !attributeValue.is Null()) |
| 149 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV alue); | 166 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV alue); |
| 167 else if (match(m_tagImpl, imgTag) && match(attributeName, srcsetAttr )) | |
| 168 m_srcSetAttribute = attributeValue; | |
| 169 | |
| 150 } else if (match(m_tagImpl, linkTag)) { | 170 } else if (match(m_tagImpl, linkTag)) { |
| 151 if (match(attributeName, hrefAttr)) | 171 if (match(attributeName, hrefAttr)) |
| 152 setUrlToLoad(attributeValue); | 172 setUrlToLoad(attributeValue, URLReplacementDisallow); |
| 153 else if (match(attributeName, relAttr)) | 173 else if (match(attributeName, relAttr)) |
| 154 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); | 174 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); |
| 155 else if (match(attributeName, mediaAttr)) | 175 else if (match(attributeName, mediaAttr)) |
| 156 m_mediaAttribute = attributeValue; | 176 m_mediaAttribute = attributeValue; |
| 157 } else if (match(m_tagImpl, inputTag)) { | 177 } else if (match(m_tagImpl, inputTag)) { |
| 158 if (match(attributeName, srcAttr)) | 178 if (match(attributeName, srcAttr)) |
| 159 setUrlToLoad(attributeValue); | 179 setUrlToLoad(attributeValue, URLReplacementDisallow); |
| 160 else if (match(attributeName, typeAttr)) | 180 else if (match(attributeName, typeAttr)) |
| 161 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName s::image()); | 181 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName s::image()); |
| 162 } | 182 } |
| 163 } | 183 } |
| 164 | 184 |
| 165 static bool relAttributeIsStyleSheet(const String& attributeValue) | 185 static bool relAttributeIsStyleSheet(const String& attributeValue) |
| 166 { | 186 { |
| 167 LinkRelAttribute rel(attributeValue); | 187 LinkRelAttribute rel(attributeValue); |
| 168 return rel.isStyleSheet() && !rel.isAlternate() && rel.iconType() == Inv alidIcon && !rel.isDNSPrefetch(); | 188 return rel.isStyleSheet() && !rel.isAlternate() && rel.iconType() == Inv alidIcon && !rel.isDNSPrefetch(); |
| 169 } | 189 } |
| 170 | 190 |
| 171 void setUrlToLoad(const String& attributeValue) | 191 void setUrlToLoad(const String& value, URLReplacement replacement) |
| 172 { | 192 { |
| 173 // We only respect the first src/href, per HTML5: | 193 // We only respect the first src/href, per HTML5: |
| 174 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenizat ion.html#attribute-name-state | 194 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenizat ion.html#attribute-name-state |
| 175 if (!m_urlToLoad.isEmpty()) | 195 if (replacement == URLReplacementDisallow && !m_urlToLoad.isEmpty()) |
| 176 return; | 196 return; |
| 177 m_urlToLoad = stripLeadingAndTrailingHTMLSpaces(attributeValue); | 197 String url = stripLeadingAndTrailingHTMLSpaces(value); |
| 198 if (url.isEmpty()) | |
| 199 return; | |
| 200 m_urlToLoad = url; | |
| 178 } | 201 } |
| 179 | 202 |
| 180 const String& charset() const | 203 const String& charset() const |
| 181 { | 204 { |
| 182 // FIXME: Its not clear that this if is needed, the loader probably igno res charset for image requests anyway. | 205 // FIXME: Its not clear that this if is needed, the loader probably igno res charset for image requests anyway. |
| 183 if (match(m_tagImpl, imgTag)) | 206 if (match(m_tagImpl, imgTag)) |
| 184 return emptyString(); | 207 return emptyString(); |
| 185 return m_charset; | 208 return m_charset; |
| 186 } | 209 } |
| 187 | 210 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 208 return true; | 231 return true; |
| 209 } | 232 } |
| 210 | 233 |
| 211 bool crossOriginModeAllowsCookies() | 234 bool crossOriginModeAllowsCookies() |
| 212 { | 235 { |
| 213 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode , "use-credentials"); | 236 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode , "use-credentials"); |
| 214 } | 237 } |
| 215 | 238 |
| 216 const StringImpl* m_tagImpl; | 239 const StringImpl* m_tagImpl; |
| 217 String m_urlToLoad; | 240 String m_urlToLoad; |
| 241 String m_srcSetAttribute; | |
| 218 String m_charset; | 242 String m_charset; |
| 219 String m_crossOriginMode; | 243 String m_crossOriginMode; |
| 220 bool m_linkIsStyleSheet; | 244 bool m_linkIsStyleSheet; |
| 221 String m_mediaAttribute; | 245 String m_mediaAttribute; |
| 222 bool m_inputIsImage; | 246 bool m_inputIsImage; |
| 247 float m_deviceScaleFactor; | |
| 223 }; | 248 }; |
| 224 | 249 |
| 225 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL) | 250 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL, float deviceSc aleFactor) |
| 226 : m_documentURL(documentURL) | 251 : m_documentURL(documentURL) |
| 227 , m_inStyle(false) | 252 , m_inStyle(false) |
| 253 , m_deviceScaleFactor(deviceScaleFactor) | |
| 228 , m_templateCount(0) | 254 , m_templateCount(0) |
| 229 { | 255 { |
| 230 } | 256 } |
| 231 | 257 |
| 232 TokenPreloadScanner::~TokenPreloadScanner() | 258 TokenPreloadScanner::~TokenPreloadScanner() |
| 233 { | 259 { |
| 234 } | 260 } |
| 235 | 261 |
| 236 TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint() | 262 TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint() |
| 237 { | 263 { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 return; | 324 return; |
| 299 } | 325 } |
| 300 if (match(tagImpl, baseTag)) { | 326 if (match(tagImpl, baseTag)) { |
| 301 // The first <base> element is the one that wins. | 327 // The first <base> element is the one that wins. |
| 302 if (!m_predictedBaseElementURL.isEmpty()) | 328 if (!m_predictedBaseElementURL.isEmpty()) |
| 303 return; | 329 return; |
| 304 updatePredictedBaseURL(token); | 330 updatePredictedBaseURL(token); |
| 305 return; | 331 return; |
| 306 } | 332 } |
| 307 | 333 |
| 308 StartTagScanner scanner(tagImpl); | 334 StartTagScanner scanner(tagImpl, m_deviceScaleFactor); |
| 309 scanner.processAttributes(token.attributes()); | 335 scanner.processAttributes(token.attributes()); |
| 310 OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predicte dBaseElementURL, source); | 336 OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predicte dBaseElementURL, source); |
| 311 if (request) | 337 if (request) |
| 312 requests.append(request.release()); | 338 requests.append(request.release()); |
| 313 return; | 339 return; |
| 314 } | 340 } |
| 315 default: { | 341 default: { |
| 316 return; | 342 return; |
| 317 } | 343 } |
| 318 } | 344 } |
| 319 } | 345 } |
| 320 | 346 |
| 321 template<typename Token> | 347 template<typename Token> |
| 322 void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) | 348 void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) |
| 323 { | 349 { |
| 324 ASSERT(m_predictedBaseElementURL.isEmpty()); | 350 ASSERT(m_predictedBaseElementURL.isEmpty()); |
| 325 if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem( hrefAttr)) | 351 if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem( hrefAttr)) |
| 326 m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingH TMLSpaces(hrefAttribute->value)).copy(); | 352 m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingH TMLSpaces(hrefAttribute->value)).copy(); |
| 327 } | 353 } |
| 328 | 354 |
| 329 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const K URL& documentURL) | 355 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const K URL& documentURL, float deviceScaleFactor) |
| 330 : m_scanner(documentURL) | 356 : m_scanner(documentURL, deviceScaleFactor) |
| 331 , m_tokenizer(HTMLTokenizer::create(options)) | 357 , m_tokenizer(HTMLTokenizer::create(options)) |
| 332 { | 358 { |
| 333 } | 359 } |
| 334 | 360 |
| 335 HTMLPreloadScanner::~HTMLPreloadScanner() | 361 HTMLPreloadScanner::~HTMLPreloadScanner() |
| 336 { | 362 { |
| 337 } | 363 } |
| 338 | 364 |
| 339 void HTMLPreloadScanner::appendToEnd(const SegmentedString& source) | 365 void HTMLPreloadScanner::appendToEnd(const SegmentedString& source) |
| 340 { | 366 { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 355 if (m_token.type() == HTMLToken::StartTag) | 381 if (m_token.type() == HTMLToken::StartTag) |
| 356 m_tokenizer->updateStateFor(AtomicString(m_token.name())); | 382 m_tokenizer->updateStateFor(AtomicString(m_token.name())); |
| 357 m_scanner.scan(m_token, m_source, requests); | 383 m_scanner.scan(m_token, m_source, requests); |
| 358 m_token.clear(); | 384 m_token.clear(); |
| 359 } | 385 } |
| 360 | 386 |
| 361 preloader->takeAndPreload(requests); | 387 preloader->takeAndPreload(requests); |
| 362 } | 388 } |
| 363 | 389 |
| 364 } | 390 } |
| OLD | NEW |