| Index: Source/core/html/parser/HTMLPreloadScanner.cpp
|
| diff --git a/Source/core/html/parser/HTMLPreloadScanner.cpp b/Source/core/html/parser/HTMLPreloadScanner.cpp
|
| index 706fb0e51034b954e74e60534ba1610ac8e53691..fa0fdaa2bde027d2d7840cad123862735cfd5f31 100644
|
| --- a/Source/core/html/parser/HTMLPreloadScanner.cpp
|
| +++ b/Source/core/html/parser/HTMLPreloadScanner.cpp
|
| @@ -108,19 +108,22 @@ public:
|
| , m_linkIsStyleSheet(false)
|
| , m_matchedMediaAttribute(true)
|
| , m_inputIsImage(false)
|
| - , m_imgSourceSize(0)
|
| + , m_sourceSize(0)
|
| , m_sourceSizeSet(false)
|
| , m_isCORSEnabled(false)
|
| , m_allowCredentials(DoNotAllowStoredCredentials)
|
| , m_mediaValues(mediaValues)
|
| {
|
| - if (!match(m_tagImpl, imgTag)
|
| - && !match(m_tagImpl, inputTag)
|
| + if (match(m_tagImpl, imgTag)
|
| + || match(m_tagImpl, sourceTag)) {
|
| + if (RuntimeEnabledFeatures::pictureSizesEnabled())
|
| + m_sourceSize = SizesAttributeParser::findEffectiveSize(String(), m_mediaValues);
|
| + return;
|
| + }
|
| + if ( !match(m_tagImpl, inputTag)
|
| && !match(m_tagImpl, linkTag)
|
| && !match(m_tagImpl, scriptTag))
|
| m_tagImpl = 0;
|
| - if (RuntimeEnabledFeatures::pictureSizesEnabled())
|
| - m_imgSourceSize = SizesAttributeParser::findEffectiveSize(String(), m_mediaValues);
|
| }
|
|
|
| enum URLReplacement {
|
| @@ -148,6 +151,18 @@ public:
|
| processAttribute(iter->name, iter->value);
|
| }
|
|
|
| + void handlePictureSourceURL(Vector<Parent>& pictureParentStack)
|
| + {
|
| + if (pictureParentStack.isEmpty() || !match(pictureParentStack.last().tagImpl, pictureTag))
|
| + return;
|
| +
|
| + Parent& parent = pictureParentStack.last();
|
| + if (match(m_tagImpl, sourceTag) && m_matchedMediaAttribute && parent.sourceURL.isEmpty())
|
| + parent.sourceURL = m_srcsetImageCandidate.toString();
|
| + else if (match(m_tagImpl, imgTag) && !parent.sourceURL.isEmpty())
|
| + setUrlToLoad(parent.sourceURL, AllowURLReplacement);
|
| + }
|
| +
|
| PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL, const SegmentedString& source)
|
| {
|
| if (!shouldPreload() || !m_matchedMediaAttribute)
|
| @@ -164,49 +179,98 @@ public:
|
|
|
| private:
|
| template<typename NameType>
|
| + void processScriptAttribute(const NameType& attributeName, const String& attributeValue)
|
| + {
|
| + // FIXME - What should happen if we have multiple crossOrigin attributes with different values?
|
| + if (match(attributeName, srcAttr))
|
| + setUrlToLoad(attributeValue, DisallowURLReplacement);
|
| + else if (match(attributeName, crossoriginAttr))
|
| + setCrossOriginAllowed(attributeValue);
|
| + }
|
| +
|
| + template<typename NameType>
|
| + void processImgAttribute(const NameType& attributeName, const String& attributeValue)
|
| + {
|
| + if (match(attributeName, srcAttr) && m_imgSrcUrl.isNull()) {
|
| + m_imgSrcUrl = attributeValue;
|
| + setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_sourceSize, attributeValue, m_srcsetImageCandidate), AllowURLReplacement);
|
| + } else if (match(attributeName, crossoriginAttr)) {
|
| + setCrossOriginAllowed(attributeValue);
|
| + } else if (match(attributeName, srcsetAttr) && m_srcsetImageCandidate.isEmpty()) {
|
| + m_srcsetAttributeValue = attributeValue;
|
| + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, attributeValue);
|
| + setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_sourceSize, m_imgSrcUrl, m_srcsetImageCandidate), AllowURLReplacement);
|
| + } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && match(attributeName, sizesAttr) && !m_sourceSizeSet) {
|
| + m_sourceSize = SizesAttributeParser::findEffectiveSize(attributeValue, m_mediaValues);
|
| + m_sourceSizeSet = true;
|
| + if (!m_srcsetImageCandidate.isEmpty()) {
|
| + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, m_srcsetAttributeValue);
|
| + setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_sourceSize, m_imgSrcUrl, m_srcsetImageCandidate), AllowURLReplacement);
|
| + }
|
| + }
|
| + }
|
| +
|
| + template<typename NameType>
|
| + void processLinkAttribute(const NameType& attributeName, const String& attributeValue)
|
| + {
|
| + // FIXME - What should happen if we have multiple rel/media/crossOrigin attributes of the same name, with different values?
|
| + if (match(attributeName, hrefAttr))
|
| + setUrlToLoad(attributeValue, DisallowURLReplacement);
|
| + else if (match(attributeName, relAttr))
|
| + m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue);
|
| + else if (match(attributeName, mediaAttr))
|
| + m_matchedMediaAttribute = mediaAttributeMatches(*m_mediaValues, attributeValue);
|
| + else if (match(attributeName, crossoriginAttr))
|
| + setCrossOriginAllowed(attributeValue);
|
| + }
|
| +
|
| + template<typename NameType>
|
| + void processInputAttribute(const NameType& attributeName, const String& attributeValue)
|
| + {
|
| + // FIXME - What should happen if we have multiple type attributes with different values?
|
| + if (match(attributeName, srcAttr))
|
| + setUrlToLoad(attributeValue, DisallowURLReplacement);
|
| + else if (match(attributeName, typeAttr))
|
| + m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image);
|
| + }
|
| +
|
| + template<typename NameType>
|
| + void processSourceAttribute(const NameType& attributeName, const String& attributeValue)
|
| + {
|
| + if (!RuntimeEnabledFeatures::pictureEnabled())
|
| + return;
|
| + if (match(attributeName, srcsetAttr) && m_srcsetImageCandidate.isEmpty()) {
|
| + m_srcsetAttributeValue = attributeValue;
|
| + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, attributeValue);
|
| + } else if (match(attributeName, sizesAttr) && !m_sourceSizeSet) {
|
| + m_sourceSize = SizesAttributeParser::findEffectiveSize(attributeValue, m_mediaValues);
|
| + m_sourceSizeSet = true;
|
| + if (!m_srcsetImageCandidate.isEmpty()) {
|
| + m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, m_srcsetAttributeValue);
|
| + }
|
| + } else if (match(attributeName, mediaAttr)) {
|
| + // FIXME - What should happen if we have multiple media attributes???
|
| + m_matchedMediaAttribute = mediaAttributeMatches(*m_mediaValues, attributeValue);
|
| + }
|
| +
|
| + }
|
| +
|
| + template<typename NameType>
|
| void processAttribute(const NameType& attributeName, const String& attributeValue)
|
| {
|
| if (match(attributeName, charsetAttr))
|
| m_charset = attributeValue;
|
|
|
| - if (match(m_tagImpl, scriptTag)) {
|
| - if (match(attributeName, srcAttr))
|
| - setUrlToLoad(attributeValue, DisallowURLReplacement);
|
| - else if (match(attributeName, crossoriginAttr))
|
| - setCrossOriginAllowed(attributeValue);
|
| - } else if (match(m_tagImpl, imgTag)) {
|
| - if (match(attributeName, srcAttr) && m_imgSrcUrl.isNull()) {
|
| - m_imgSrcUrl = attributeValue;
|
| - setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_imgSourceSize, attributeValue, m_srcsetImageCandidate), AllowURLReplacement);
|
| - } else if (match(attributeName, crossoriginAttr)) {
|
| - setCrossOriginAllowed(attributeValue);
|
| - } else if (match(attributeName, srcsetAttr) && m_srcsetImageCandidate.isEmpty()) {
|
| - m_imgSrcsetAttributeValue = attributeValue;
|
| - m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_imgSourceSize, attributeValue);
|
| - setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_imgSourceSize, m_imgSrcUrl, m_srcsetImageCandidate), AllowURLReplacement);
|
| - } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && match(attributeName, sizesAttr) && !m_sourceSizeSet) {
|
| - m_imgSourceSize = SizesAttributeParser::findEffectiveSize(attributeValue, m_mediaValues);
|
| - m_sourceSizeSet = true;
|
| - if (!m_srcsetImageCandidate.isEmpty()) {
|
| - m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_imgSourceSize, m_imgSrcsetAttributeValue);
|
| - setUrlToLoad(bestFitSourceForImageAttributes(m_mediaValues->devicePixelRatio(), m_imgSourceSize, m_imgSrcUrl, m_srcsetImageCandidate), AllowURLReplacement);
|
| - }
|
| - }
|
| - } else if (match(m_tagImpl, linkTag)) {
|
| - if (match(attributeName, hrefAttr))
|
| - setUrlToLoad(attributeValue, DisallowURLReplacement);
|
| - else if (match(attributeName, relAttr))
|
| - m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue);
|
| - else if (match(attributeName, mediaAttr))
|
| - m_matchedMediaAttribute = mediaAttributeMatches(*m_mediaValues, attributeValue);
|
| - else if (match(attributeName, crossoriginAttr))
|
| - setCrossOriginAllowed(attributeValue);
|
| - } else if (match(m_tagImpl, inputTag)) {
|
| - if (match(attributeName, srcAttr))
|
| - setUrlToLoad(attributeValue, DisallowURLReplacement);
|
| - else if (match(attributeName, typeAttr))
|
| - m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image);
|
| - }
|
| + if (match(m_tagImpl, scriptTag))
|
| + processScriptAttribute(attributeName, attributeValue);
|
| + else if (match(m_tagImpl, imgTag))
|
| + processImgAttribute(attributeName, attributeValue);
|
| + else if (match(m_tagImpl, linkTag))
|
| + processLinkAttribute(attributeName, attributeValue);
|
| + else if (match(m_tagImpl, inputTag))
|
| + processInputAttribute(attributeName, attributeValue);
|
| + else if (match(m_tagImpl, sourceTag))
|
| + processSourceAttribute(attributeName, attributeValue);
|
| }
|
|
|
| static bool relAttributeIsStyleSheet(const String& attributeValue)
|
| @@ -285,8 +349,8 @@ private:
|
| bool m_matchedMediaAttribute;
|
| bool m_inputIsImage;
|
| String m_imgSrcUrl;
|
| - String m_imgSrcsetAttributeValue;
|
| - unsigned m_imgSourceSize;
|
| + String m_srcsetAttributeValue;
|
| + unsigned m_sourceSize;
|
| bool m_sourceSizeSet;
|
| bool m_isCORSEnabled;
|
| StoredCredentials m_allowCredentials;
|
| @@ -333,6 +397,26 @@ void TokenPreloadScanner::scan(const CompactHTMLToken& token, const SegmentedStr
|
| scanCommon(token, source, requests);
|
| }
|
|
|
| +static bool startNesting(const StringImpl* tagImpl, bool selfClosing)
|
| +{
|
| + if (selfClosing
|
| + || match(tagImpl, sourceTag)
|
| + || match(tagImpl, imgTag)
|
| + || match(tagImpl, areaTag)
|
| + || match(tagImpl, baseTag)
|
| + || match(tagImpl, brTag)
|
| + || match(tagImpl, colTag)
|
| + || match(tagImpl, hrTag)
|
| + || match(tagImpl, inputTag)
|
| + || match(tagImpl, linkTag)
|
| + || match(tagImpl, metaTag)
|
| + || match(tagImpl, paramTag)
|
| + || match(tagImpl, commandTag)
|
| + || match(tagImpl, keygenTag))
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| template<typename Token>
|
| void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString& source, PreloadRequestStream& requests)
|
| {
|
| @@ -350,6 +434,8 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString&
|
| --m_templateCount;
|
| return;
|
| }
|
| + if (!m_pictureParentStack.isEmpty() && startNesting(tagImpl, token.selfClosing()) && m_pictureParentStack.last().tagImpl == tagImpl)
|
| + m_pictureParentStack.removeLast();
|
| if (match(tagImpl, styleTag)) {
|
| if (m_inStyle)
|
| m_cssScanner.reset();
|
| @@ -361,6 +447,10 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString&
|
| if (m_templateCount)
|
| return;
|
| const StringImpl* tagImpl = tagImplFor(token.data());
|
| + if (RuntimeEnabledFeatures::pictureEnabled()
|
| + && ((match(tagImpl, pictureTag)) || (!m_pictureParentStack.isEmpty() && startNesting(tagImpl, token.selfClosing())))) {
|
| + m_pictureParentStack.append(Parent(tagImpl));
|
| + }
|
| if (match(tagImpl, templateTag)) {
|
| ++m_templateCount;
|
| return;
|
| @@ -379,6 +469,7 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString&
|
|
|
| StartTagScanner scanner(tagImpl, m_mediaValues);
|
| scanner.processAttributes(token.attributes());
|
| + scanner.handlePictureSourceURL(m_pictureParentStack);
|
| OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predictedBaseElementURL, source);
|
| if (request)
|
| requests.append(request.release());
|
|
|