diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/html/parser/HTMLPreloadScanner.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/html/parser/HTMLPreloadScanner.cpp')
-rw-r--r-- | Source/WebCore/html/parser/HTMLPreloadScanner.cpp | 252 |
1 files changed, 86 insertions, 166 deletions
diff --git a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp index dee9ea660..51c81e189 100644 --- a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp +++ b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp @@ -30,13 +30,9 @@ #include "HTMLNames.h" #include "HTMLParserIdioms.h" -#include "HTMLSrcsetParser.h" #include "HTMLTokenizer.h" #include "InputTypeNames.h" #include "LinkRelAttribute.h" -#include "MediaList.h" -#include "MediaQueryEvaluator.h" -#include "SourceSizeList.h" #include <wtf/MainThread.h> namespace WebCore { @@ -60,19 +56,12 @@ TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const HTMLToken::DataVe return TagId::Base; if (tagName == templateTag) return TagId::Template; - if (tagName == metaTag) - return TagId::Meta; - if (tagName == pictureTag) - return TagId::Picture; - if (tagName == sourceTag) - return TagId::Source; return TagId::Unknown; } String TokenPreloadScanner::initiatorFor(TagId tagId) { switch (tagId) { - case TagId::Source: case TagId::Img: return "img"; case TagId::Input: @@ -85,8 +74,6 @@ String TokenPreloadScanner::initiatorFor(TagId tagId) case TagId::Style: case TagId::Base: case TagId::Template: - case TagId::Meta: - case TagId::Picture: ASSERT_NOT_REACHED(); return "unknown"; } @@ -99,42 +86,27 @@ public: explicit StartTagScanner(TagId tagId, float deviceScaleFactor = 1.0) : m_tagId(tagId) , m_linkIsStyleSheet(false) - , m_metaIsViewport(false) , m_inputIsImage(false) , m_deviceScaleFactor(deviceScaleFactor) { } - void processAttributes(const HTMLToken::AttributeList& attributes, Document& document, Vector<bool>& pictureState) + void processAttributes(const HTMLToken::AttributeList& attributes) { ASSERT(isMainThread()); if (m_tagId >= TagId::Unknown) return; - - for (auto& attribute : attributes) { - AtomicString attributeName(attribute.name); - String attributeValue = StringImpl::create8BitIfPossible(attribute.value); - processAttribute(attributeName, attributeValue, document, pictureState); - } - - if (m_tagId == TagId::Source && !pictureState.isEmpty() && !pictureState.last() && m_mediaMatched && !m_srcSetAttribute.isEmpty()) { - float sourceSize = parseSizesAttribute(m_sizesAttribute, document.renderView(), document.frame()); - ImageCandidate imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute, sourceSize); - if (!imageCandidate.isEmpty()) { - pictureState.last() = true; - setUrlToLoad(imageCandidate.string.toString(), true); - } - } - - // Resolve between src and srcSet if we have them and the tag is img. - if (m_tagId == TagId::Img && !m_srcSetAttribute.isEmpty()) { - float sourceSize = parseSizesAttribute(m_sizesAttribute, document.renderView(), document.frame()); - ImageCandidate imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute, sourceSize); - setUrlToLoad(imageCandidate.string.toString(), true); + for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { + AtomicString attributeName(iter->name); + String attributeValue = StringImpl::create8BitIfPossible(iter->value); + processAttribute(attributeName, attributeValue); } - if (m_metaIsViewport && !m_metaContent.isNull()) - document.processViewport(m_metaContent, ViewportArguments::ViewportMeta); + // Resolve between src and srcSet if we have them. + if (!m_srcSetAttribute.isEmpty()) { + String srcMatchingScale = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute); + setUrlToLoad(srcMatchingScale, true); + } } std::unique_ptr<PreloadRequest> createPreloadRequest(const URL& predictedBaseURL) @@ -156,92 +128,38 @@ public: } private: - void processImageAndScriptAttribute(const AtomicString& attributeName, const String& attributeValue) + template<typename NameType> + void processAttribute(const NameType& attributeName, const String& attributeValue) { - if (match(attributeName, srcAttr)) - setUrlToLoad(attributeValue); - else if (match(attributeName, crossoriginAttr) && !attributeValue.isNull()) - m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeValue); - else if (match(attributeName, charsetAttr)) + if (match(attributeName, charsetAttr)) m_charset = attributeValue; - } - void processAttribute(const AtomicString& attributeName, const String& attributeValue, Document& document, const Vector<bool>& pictureState) - { - bool inPicture = !pictureState.isEmpty(); - bool alreadyMatchedSource = inPicture && pictureState.last(); - - switch (m_tagId) { - case TagId::Img: - if (inPicture && alreadyMatchedSource) - break; - if (match(attributeName, srcsetAttr) && m_srcSetAttribute.isNull()) { - m_srcSetAttribute = attributeValue; - break; - } - if (match(attributeName, sizesAttr) && m_sizesAttribute.isNull()) { - m_sizesAttribute = attributeValue; - break; - } - processImageAndScriptAttribute(attributeName, attributeValue); - break; - case TagId::Source: - if (inPicture && alreadyMatchedSource) - break; - if (match(attributeName, srcsetAttr) && m_srcSetAttribute.isNull()) { + if (m_tagId == TagId::Script || m_tagId == TagId::Img) { + if (match(attributeName, srcAttr)) + setUrlToLoad(attributeValue); + else if (match(attributeName, srcsetAttr)) m_srcSetAttribute = attributeValue; - break; - } - if (match(attributeName, sizesAttr) && m_sizesAttribute.isNull()) { - m_sizesAttribute = attributeValue; - break; - } - if (match(attributeName, mediaAttr) && m_mediaAttribute.isNull()) { - m_mediaAttribute = attributeValue; - Ref<MediaQuerySet> mediaSet = MediaQuerySet::createAllowingDescriptionSyntax(attributeValue); - Vector<std::unique_ptr<MediaQueryResult>> viewportDependentMediaQueryResults; - MediaQueryEvaluator evaluator(document.printing() ? "print" : "screen", document.frame(), document.documentElement() ? document.documentElement()->computedStyle() : nullptr); - m_mediaMatched = evaluator.evalCheckingViewportDependentResults(mediaSet.ptr(), viewportDependentMediaQueryResults); - } - break; - case TagId::Script: - processImageAndScriptAttribute(attributeName, attributeValue); - break; - case TagId::Link: + else if (match(attributeName, crossoriginAttr) && !attributeValue.isNull()) + m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeValue); + } else if (m_tagId == TagId::Link) { if (match(attributeName, hrefAttr)) setUrlToLoad(attributeValue); else if (match(attributeName, relAttr)) m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); else if (match(attributeName, mediaAttr)) m_mediaAttribute = attributeValue; - else if (match(attributeName, charsetAttr)) - m_charset = attributeValue; - break; - case TagId::Input: + } else if (m_tagId == TagId::Input) { if (match(attributeName, srcAttr)) setUrlToLoad(attributeValue); else if (match(attributeName, typeAttr)) - m_inputIsImage = equalLettersIgnoringASCIICase(attributeValue, "image"); - break; - case TagId::Meta: - if (match(attributeName, contentAttr)) - m_metaContent = attributeValue; - else if (match(attributeName, nameAttr)) - m_metaIsViewport = equalLettersIgnoringASCIICase(attributeValue, "viewport"); - break; - case TagId::Base: - case TagId::Style: - case TagId::Template: - case TagId::Picture: - case TagId::Unknown: - break; + m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image()); } } static bool relAttributeIsStyleSheet(const String& attributeValue) { - LinkRelAttribute parsedAttribute { attributeValue }; - return parsedAttribute.isStyleSheet && !parsedAttribute.isAlternate && parsedAttribute.iconType == InvalidIcon && !parsedAttribute.isDNSPrefetch; + LinkRelAttribute rel(attributeValue); + return rel.m_isStyleSheet && !rel.m_isAlternate && rel.m_iconType == InvalidIcon && !rel.m_isDNSPrefetch; } void setUrlToLoad(const String& value, bool allowReplacement = false) @@ -258,30 +176,20 @@ private: const String& charset() const { + // FIXME: Its not clear that this if is needed, the loader probably ignores charset for image requests anyway. + if (m_tagId == TagId::Img) + return emptyString(); return m_charset; } CachedResource::Type resourceType() const { - switch (m_tagId) { - case TagId::Script: + if (m_tagId == TagId::Script) return CachedResource::Script; - case TagId::Img: - case TagId::Input: - case TagId::Source: - ASSERT(m_tagId != TagId::Input || m_inputIsImage); + if (m_tagId == TagId::Img || (m_tagId == TagId::Input && m_inputIsImage)) return CachedResource::ImageResource; - case TagId::Link: - ASSERT(m_linkIsStyleSheet); + if (m_tagId == TagId::Link && m_linkIsStyleSheet) return CachedResource::CSSStyleSheet; - case TagId::Meta: - case TagId::Unknown: - case TagId::Style: - case TagId::Base: - case TagId::Template: - case TagId::Picture: - break; - } ASSERT_NOT_REACHED(); return CachedResource::RawResource; } @@ -291,9 +199,6 @@ private: if (m_urlToLoad.isEmpty()) return false; - if (protocolIs(m_urlToLoad, "data") || protocolIs(m_urlToLoad, "about")) - return false; - if (m_tagId == TagId::Link && !m_linkIsStyleSheet) return false; @@ -305,41 +210,69 @@ private: bool crossOriginModeAllowsCookies() { - return m_crossOriginMode.isNull() || equalLettersIgnoringASCIICase(m_crossOriginMode, "use-credentials"); + return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode, "use-credentials"); } TagId m_tagId; String m_urlToLoad; String m_srcSetAttribute; - String m_sizesAttribute; - bool m_mediaMatched { true }; String m_charset; String m_crossOriginMode; bool m_linkIsStyleSheet; String m_mediaAttribute; - String m_metaContent; - bool m_metaIsViewport; bool m_inputIsImage; float m_deviceScaleFactor; }; TokenPreloadScanner::TokenPreloadScanner(const URL& documentURL, float deviceScaleFactor) : m_documentURL(documentURL) + , m_inStyle(false) , m_deviceScaleFactor(deviceScaleFactor) +#if ENABLE(TEMPLATE_ELEMENT) + , m_templateCount(0) +#endif +{ +} + +TokenPreloadScanner::~TokenPreloadScanner() +{ +} + +TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint() +{ + TokenPreloadScannerCheckpoint checkpoint = m_checkpoints.size(); + m_checkpoints.append(Checkpoint(m_predictedBaseElementURL, m_inStyle +#if ENABLE(TEMPLATE_ELEMENT) + , m_templateCount +#endif + )); + return checkpoint; +} + +void TokenPreloadScanner::rewindTo(TokenPreloadScannerCheckpoint checkpointIndex) { + ASSERT(checkpointIndex < m_checkpoints.size()); // If this ASSERT fires, checkpointIndex is invalid. + const Checkpoint& checkpoint = m_checkpoints[checkpointIndex]; + m_predictedBaseElementURL = checkpoint.predictedBaseElementURL; + m_inStyle = checkpoint.inStyle; +#if ENABLE(TEMPLATE_ELEMENT) + m_templateCount = checkpoint.templateCount; +#endif + m_cssScanner.reset(); + m_checkpoints.clear(); } -void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<PreloadRequest>>& requests, Document& document) +void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<PreloadRequest>>& requests) { switch (token.type()) { case HTMLToken::Character: if (!m_inStyle) return; - m_cssScanner.scan(token.characters(), requests); + m_cssScanner.scan(token.data(), requests); return; case HTMLToken::EndTag: { - TagId tagId = tagIdFor(token.name()); + TagId tagId = tagIdFor(token.data()); #if ENABLE(TEMPLATE_ELEMENT) if (tagId == TagId::Template) { if (m_templateCount) @@ -351,9 +284,7 @@ void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<Pr if (m_inStyle) m_cssScanner.reset(); m_inStyle = false; - } else if (tagId == TagId::Picture && !m_pictureSourceState.isEmpty()) - m_pictureSourceState.removeLast(); - + } return; } @@ -362,7 +293,7 @@ void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<Pr if (m_templateCount) return; #endif - TagId tagId = tagIdFor(token.name()); + TagId tagId = tagIdFor(token.data()); #if ENABLE(TEMPLATE_ELEMENT) if (tagId == TagId::Template) { ++m_templateCount; @@ -380,15 +311,11 @@ void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<Pr updatePredictedBaseURL(token); return; } - if (tagId == TagId::Picture) { - m_pictureSourceState.append(false); - return; - } StartTagScanner scanner(tagId, m_deviceScaleFactor); - scanner.processAttributes(token.attributes(), document, m_pictureSourceState); + scanner.processAttributes(token.attributes()); if (auto request = scanner.createPreloadRequest(m_predictedBaseElementURL)) - requests.append(WTFMove(request)); + requests.append(std::move(request)); return; } @@ -397,16 +324,21 @@ void TokenPreloadScanner::scan(const HTMLToken& token, Vector<std::unique_ptr<Pr } } -void TokenPreloadScanner::updatePredictedBaseURL(const HTMLToken& token) +template<typename Token> +void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) { ASSERT(m_predictedBaseElementURL.isEmpty()); - if (auto* hrefAttribute = findAttribute(token.attributes(), hrefAttr.localName().string())) - m_predictedBaseElementURL = URL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(StringImpl::create8BitIfPossible(hrefAttribute->value))).isolatedCopy(); + if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem(hrefAttr)) + m_predictedBaseElementURL = URL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefAttribute->value)).copy(); } HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const URL& documentURL, float deviceScaleFactor) : m_scanner(documentURL, deviceScaleFactor) - , m_tokenizer(options) + , m_tokenizer(std::make_unique<HTMLTokenizer>(options)) +{ +} + +HTMLPreloadScanner::~HTMLPreloadScanner() { } @@ -415,36 +347,24 @@ void HTMLPreloadScanner::appendToEnd(const SegmentedString& source) m_source.append(source); } -void HTMLPreloadScanner::scan(HTMLResourcePreloader& preloader, Document& document) +void HTMLPreloadScanner::scan(HTMLResourcePreloader* preloader, const URL& startingBaseElementURL) { ASSERT(isMainThread()); // HTMLTokenizer::updateStateFor only works on the main thread. - const URL& startingBaseElementURL = document.baseElementURL(); - // When we start scanning, our best prediction of the baseElementURL is the real one! if (!startingBaseElementURL.isEmpty()) m_scanner.setPredictedBaseElementURL(startingBaseElementURL); PreloadRequestStream requests; - while (auto token = m_tokenizer.nextToken(m_source)) { - if (token->type() == HTMLToken::StartTag) - m_tokenizer.updateStateFor(AtomicString(token->name())); - m_scanner.scan(*token, requests, document); + while (m_tokenizer->nextToken(m_source, m_token)) { + if (m_token.type() == HTMLToken::StartTag) + m_tokenizer->updateStateFor(AtomicString(m_token.name())); + m_scanner.scan(m_token, requests); + m_token.clear(); } - preloader.preload(WTFMove(requests)); -} - -bool testPreloadScannerViewportSupport(Document* document) -{ - ASSERT(document); - HTMLParserOptions options(*document); - HTMLPreloadScanner scanner(options, document->url()); - HTMLResourcePreloader preloader(*document); - scanner.appendToEnd(String("<meta name=viewport content='width=400'>")); - scanner.scan(preloader, *document); - return (document->viewportArguments().width == 400); + preloader->preload(std::move(requests)); } } |