Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / parser / HTMLPreloadScanner.cpp
index 706fb0e..351484f 100644 (file)
@@ -28,9 +28,8 @@
 #include "config.h"
 #include "core/html/parser/HTMLPreloadScanner.h"
 
-#include "HTMLNames.h"
-#include "InputTypeNames.h"
-#include "RuntimeEnabledFeatures.h"
+#include "core/HTMLNames.h"
+#include "core/InputTypeNames.h"
 #include "core/css/MediaList.h"
 #include "core/css/MediaQueryEvaluator.h"
 #include "core/css/MediaValues.h"
 #include "core/html/parser/HTMLParserIdioms.h"
 #include "core/html/parser/HTMLSrcsetParser.h"
 #include "core/html/parser/HTMLTokenizer.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/TraceEvent.h"
 #include "wtf/MainThread.h"
 
-namespace WebCore {
+namespace blink {
 
 using namespace HTMLNames;
 
@@ -97,7 +97,7 @@ static String initiatorFor(const StringImpl* tagImpl)
 static bool mediaAttributeMatches(const MediaValues& mediaValues, const String& attributeValue)
 {
     RefPtrWillBeRawPtr<MediaQuerySet> mediaQueries = MediaQuerySet::createOffMainThread(attributeValue);
-    MediaQueryEvaluator mediaQueryEvaluator("screen", mediaValues);
+    MediaQueryEvaluator mediaQueryEvaluator(mediaValues);
     return mediaQueryEvaluator.eval(mediaQueries.get());
 }
 
@@ -108,19 +108,23 @@ public:
         , m_linkIsStyleSheet(false)
         , m_matchedMediaAttribute(true)
         , m_inputIsImage(false)
-        , m_imgSourceSize(0)
+        , m_sourceSize(0)
         , m_sourceSizeSet(false)
         , m_isCORSEnabled(false)
+        , m_defer(FetchRequest::NoDefer)
         , 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(m_mediaValues, String()).length();
+            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 +152,14 @@ public:
             processAttribute(iter->name, iter->value);
     }
 
+    void handlePictureSourceURL(String& sourceURL)
+    {
+        if (match(m_tagImpl, sourceTag) && m_matchedMediaAttribute && sourceURL.isEmpty())
+            sourceURL = m_srcsetImageCandidate.toString();
+        else if (match(m_tagImpl, imgTag) && !sourceURL.isEmpty())
+            setUrlToLoad(sourceURL, AllowURLReplacement);
+    }
+
     PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL, const SegmentedString& source)
     {
         if (!shouldPreload() || !m_matchedMediaAttribute)
@@ -159,54 +171,108 @@ public:
         if (isCORSEnabled())
             request->setCrossOriginEnabled(allowStoredCredentials());
         request->setCharset(charset());
+        request->setDefer(m_defer);
         return request.release();
     }
 
 private:
     template<typename NameType>
+    void processScriptAttribute(const NameType& attributeName, const String& attributeValue)
+    {
+        // FIXME - Don't set crossorigin multiple times.
+        if (match(attributeName, srcAttr))
+            setUrlToLoad(attributeValue, DisallowURLReplacement);
+        else if (match(attributeName, crossoriginAttr))
+            setCrossOriginAllowed(attributeValue);
+        else if (match(attributeName, asyncAttr))
+            setDefer(FetchRequest::LazyLoad);
+        else if (match(attributeName, deferAttr))
+            setDefer(FetchRequest::LazyLoad);
+    }
+
+    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(m_mediaValues, attributeValue).length();
+            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 - Don't set rel/media/crossorigin multiple times.
+        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 - Don't set type multiple times.
+        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(m_mediaValues, attributeValue).length();
+            m_sourceSizeSet = true;
+            if (!m_srcsetImageCandidate.isEmpty()) {
+                m_srcsetImageCandidate = bestFitSourceForSrcsetAttribute(m_mediaValues->devicePixelRatio(), m_sourceSize, m_srcsetAttributeValue);
+            }
+        } else if (match(attributeName, mediaAttr)) {
+            // FIXME - Don't match media multiple times.
+            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)
@@ -277,6 +343,16 @@ private:
             m_allowCredentials = DoNotAllowStoredCredentials;
     }
 
+    void setDefer(FetchRequest::DeferOption defer)
+    {
+        m_defer = defer;
+    }
+
+    bool defer() const
+    {
+        return m_defer;
+    }
+
     const StringImpl* m_tagImpl;
     String m_urlToLoad;
     ImageCandidate m_srcsetImageCandidate;
@@ -285,10 +361,11 @@ 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;
+    FetchRequest::DeferOption m_defer;
     StoredCredentials m_allowCredentials;
     RefPtr<MediaValues> m_mediaValues;
 };
@@ -296,6 +373,7 @@ private:
 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL, PassRefPtr<MediaValues> mediaValues)
     : m_documentURL(documentURL)
     , m_inStyle(false)
+    , m_inPicture(false)
     , m_templateCount(0)
     , m_mediaValues(mediaValues)
 {
@@ -354,7 +432,10 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString&
             if (m_inStyle)
                 m_cssScanner.reset();
             m_inStyle = false;
+            return;
         }
+        if (match(tagImpl, pictureTag))
+            m_inPicture = false;
         return;
     }
     case HTMLToken::StartTag: {
@@ -376,9 +457,16 @@ void TokenPreloadScanner::scanCommon(const Token& token, const SegmentedString&
             updatePredictedBaseURL(token);
             return;
         }
+        if (RuntimeEnabledFeatures::pictureEnabled() && (match(tagImpl, pictureTag))) {
+            m_inPicture = true;
+            m_pictureSourceURL = String();
+            return;
+        }
 
         StartTagScanner scanner(tagImpl, m_mediaValues);
         scanner.processAttributes(token.attributes());
+        if (m_inPicture)
+            scanner.handlePictureSourceURL(m_pictureSourceURL);
         OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predictedBaseElementURL, source);
         if (request)
             requests.append(request.release());
@@ -417,7 +505,7 @@ void HTMLPreloadScanner::scan(HTMLResourcePreloader* preloader, const KURL& star
 {
     ASSERT(isMainThread()); // HTMLTokenizer::updateStateFor only works on the main thread.
 
-    TRACE_EVENT1("webkit", "HTMLPreloadScanner::scan", "source_length", m_source.length());
+    TRACE_EVENT1("blink", "HTMLPreloadScanner::scan", "source_length", m_source.length());
 
     // When we start scanning, our best prediction of the baseElementURL is the real one!
     if (!startingBaseElementURL.isEmpty())