2010-06-17 Adam Barth <abarth@webkit.org>
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Jun 2010 02:01:00 +0000 (02:01 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Jun 2010 02:01:00 +0000 (02:01 +0000)
        Reviewed by Eric Seidel.

        Add CSS scanning to HTML5PreloadScanner
        https://bugs.webkit.org/show_bug.cgi?id=40802

        This patch just cribs the CSS preload scanning algorithm from the old
        preload scanner.  We also invented a way of testing the preload
        scanner.

        Tests: fast/preloader/image.html
               fast/preloader/link.html
               fast/preloader/script.html
               fast/preloader/style.html

        * Android.mk:
        * GNUmakefile.am:
        * WebCore.gypi:
        * WebCore.pro:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * html/CSSPreloadScanner.cpp: Added.
        (WebCore::isWhitespace):
        (WebCore::CSSPreloadScanner::CSSPreloadScanner):
        (WebCore::CSSPreloadScanner::reset):
        (WebCore::CSSPreloadScanner::scan):
        (WebCore::CSSPreloadScanner::tokenize):
        (WebCore::CSSPreloadScanner::emitRule):
        * html/CSSPreloadScanner.h: Added.
        (WebCore::CSSPreloadScanner::):
        * html/HTML5PreloadScanner.cpp:
        (WebCore::HTML5PreloadScanner::HTML5PreloadScanner):
        (WebCore::HTML5PreloadScanner::processToken):
        (WebCore::HTML5PreloadScanner::scanningBody):
        * html/HTML5PreloadScanner.h:
2010-06-17  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        Add CSS scanning to HTML5PreloadScanner
        https://bugs.webkit.org/show_bug.cgi?id=40802

        Add a testing framework for the preload scanner.  These test cover
        basic preloader behavior.  They have a small hack to work around a bug
        in the preload scanner discovered while writing the tests.  I'll fix
        the bug and remove the hack in a followup patch.

        * fast/preloader/image-expected.txt: Added.
        * fast/preloader/image.html: Added.
        * fast/preloader/link-expected.txt: Added.
        * fast/preloader/link.html: Added.
        * fast/preloader/resources/image1.png: Added.
        * fast/preloader/resources/link1.css: Added.
        * fast/preloader/resources/script1.js: Added.
        * fast/preloader/resources/style1.css: Added.
        * fast/preloader/script-expected.txt: Added.
        * fast/preloader/script.html: Added.
        * fast/preloader/style-expected.txt: Added.
        * fast/preloader/style.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@61366 268f45cc-cd09-0410-ab3c-d52691b4dbfc

24 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/preloader/image-expected.txt [new file with mode: 0644]
LayoutTests/fast/preloader/image.html [new file with mode: 0644]
LayoutTests/fast/preloader/link-expected.txt [new file with mode: 0644]
LayoutTests/fast/preloader/link.html [new file with mode: 0644]
LayoutTests/fast/preloader/resources/image1.png [new file with mode: 0644]
LayoutTests/fast/preloader/resources/link1.css [new file with mode: 0644]
LayoutTests/fast/preloader/resources/script1.js [new file with mode: 0644]
LayoutTests/fast/preloader/resources/style1.css [new file with mode: 0644]
LayoutTests/fast/preloader/script-expected.txt [new file with mode: 0644]
LayoutTests/fast/preloader/script.html [new file with mode: 0644]
LayoutTests/fast/preloader/style-expected.txt [new file with mode: 0644]
LayoutTests/fast/preloader/style.html [new file with mode: 0644]
WebCore/Android.mk
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/html/CSSPreloadScanner.cpp [new file with mode: 0644]
WebCore/html/CSSPreloadScanner.h [new file with mode: 0644]
WebCore/html/HTML5PreloadScanner.cpp
WebCore/html/HTML5PreloadScanner.h

index 619b685..3c2fe93 100644 (file)
@@ -1,3 +1,28 @@
+2010-06-17  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        Add CSS scanning to HTML5PreloadScanner
+        https://bugs.webkit.org/show_bug.cgi?id=40802
+
+        Add a testing framework for the preload scanner.  These test cover
+        basic preloader behavior.  They have a small hack to work around a bug
+        in the preload scanner discovered while writing the tests.  I'll fix
+        the bug and remove the hack in a followup patch.
+
+        * fast/preloader/image-expected.txt: Added.
+        * fast/preloader/image.html: Added.
+        * fast/preloader/link-expected.txt: Added.
+        * fast/preloader/link.html: Added.
+        * fast/preloader/resources/image1.png: Added.
+        * fast/preloader/resources/link1.css: Added.
+        * fast/preloader/resources/script1.js: Added.
+        * fast/preloader/resources/style1.css: Added.
+        * fast/preloader/script-expected.txt: Added.
+        * fast/preloader/script.html: Added.
+        * fast/preloader/style-expected.txt: Added.
+        * fast/preloader/style.html: Added.
+
 2010-06-17  Dimitri Glazkov  <dglazkov@chromium.org>
 
         Unreviewed, Chromium expectations update.
diff --git a/LayoutTests/fast/preloader/image-expected.txt b/LayoutTests/fast/preloader/image-expected.txt
new file mode 100644 (file)
index 0000000..60abe31
--- /dev/null
@@ -0,0 +1,5 @@
+image1.png has MIME type image/png
+This test requires DumpRenderTree to see the log of what resources are loaded.
+
+<img src=resources/image1.png>
+
diff --git a/LayoutTests/fast/preloader/image.html b/LayoutTests/fast/preloader/image.html
new file mode 100644 (file)
index 0000000..28250a4
--- /dev/null
@@ -0,0 +1,11 @@
+<body>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpResourceResponseMIMETypes();
+}
+</script>
+This test requires DumpRenderTree to see the log of what resources are loaded.
+<script src=resources/non-existant.js></script>
+<script>document.write("<plain" + "text>");</script>
+<img src=resources/image1.png>
diff --git a/LayoutTests/fast/preloader/link-expected.txt b/LayoutTests/fast/preloader/link-expected.txt
new file mode 100644 (file)
index 0000000..16ba57d
--- /dev/null
@@ -0,0 +1,5 @@
+link1.css has MIME type text/css
+This test requires DumpRenderTree to see the log of what resources are loaded.
+
+<link href=resources/link1.css rel="stylesheet">
+
diff --git a/LayoutTests/fast/preloader/link.html b/LayoutTests/fast/preloader/link.html
new file mode 100644 (file)
index 0000000..1b8b9b1
--- /dev/null
@@ -0,0 +1,11 @@
+<body>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpResourceResponseMIMETypes();
+}
+</script>
+This test requires DumpRenderTree to see the log of what resources are loaded.
+<script src=resources/non-existant.js></script>
+<script>document.write("<plain" + "text>");</script>
+<link href=resources/link1.css rel="stylesheet">
diff --git a/LayoutTests/fast/preloader/resources/image1.png b/LayoutTests/fast/preloader/resources/image1.png
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LayoutTests/fast/preloader/resources/link1.css b/LayoutTests/fast/preloader/resources/link1.css
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LayoutTests/fast/preloader/resources/script1.js b/LayoutTests/fast/preloader/resources/script1.js
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LayoutTests/fast/preloader/resources/style1.css b/LayoutTests/fast/preloader/resources/style1.css
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/LayoutTests/fast/preloader/script-expected.txt b/LayoutTests/fast/preloader/script-expected.txt
new file mode 100644 (file)
index 0000000..cb889dd
--- /dev/null
@@ -0,0 +1,5 @@
+script1.js has MIME type application/x-javascript
+This test requires DumpRenderTree to see the log of what resources are loaded.
+
+<script src=resources/script1.js></script>
+
diff --git a/LayoutTests/fast/preloader/script.html b/LayoutTests/fast/preloader/script.html
new file mode 100644 (file)
index 0000000..57ff781
--- /dev/null
@@ -0,0 +1,11 @@
+<body>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpResourceResponseMIMETypes();
+}
+</script>
+This test requires DumpRenderTree to see the log of what resources are loaded.
+<script src=resources/non-existant.js></script>
+<script>document.write("<plain" + "text>");</script>
+<script src=resources/script1.js></script>
diff --git a/LayoutTests/fast/preloader/style-expected.txt b/LayoutTests/fast/preloader/style-expected.txt
new file mode 100644 (file)
index 0000000..145df0e
--- /dev/null
@@ -0,0 +1,7 @@
+style1.css has MIME type text/css
+This test requires DumpRenderTree to see the log of what resources are loaded.
+
+<style>
+@import "resources/style1.css";
+</style>
+
diff --git a/LayoutTests/fast/preloader/style.html b/LayoutTests/fast/preloader/style.html
new file mode 100644 (file)
index 0000000..231bb78
--- /dev/null
@@ -0,0 +1,13 @@
+<body>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpResourceResponseMIMETypes();
+}
+</script>
+This test requires DumpRenderTree to see the log of what resources are loaded.
+<script src=resources/non-existant.js></script>
+<script>document.write("<plain" + "text>");</script>
+<style>
+@import "resources/style1.css";
+</style>
index 36c1799..df25d56 100644 (file)
@@ -244,6 +244,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
        html/AsyncImageResizer.cpp \
        html/Blob.cpp \
        html/CollectionCache.cpp \
+       html/CSSPreloadScanner.cpp \
        html/DOMFormData.cpp \
        html/File.cpp \
        html/FileList.cpp \
index 86db8b9..1ae8aee 100644 (file)
@@ -1,3 +1,40 @@
+2010-06-17  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        Add CSS scanning to HTML5PreloadScanner
+        https://bugs.webkit.org/show_bug.cgi?id=40802
+
+        This patch just cribs the CSS preload scanning algorithm from the old
+        preload scanner.  We also invented a way of testing the preload
+        scanner.
+
+        Tests: fast/preloader/image.html
+               fast/preloader/link.html
+               fast/preloader/script.html
+               fast/preloader/style.html
+
+        * Android.mk:
+        * GNUmakefile.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * html/CSSPreloadScanner.cpp: Added.
+        (WebCore::isWhitespace):
+        (WebCore::CSSPreloadScanner::CSSPreloadScanner):
+        (WebCore::CSSPreloadScanner::reset):
+        (WebCore::CSSPreloadScanner::scan):
+        (WebCore::CSSPreloadScanner::tokenize):
+        (WebCore::CSSPreloadScanner::emitRule):
+        * html/CSSPreloadScanner.h: Added.
+        (WebCore::CSSPreloadScanner::):
+        * html/HTML5PreloadScanner.cpp:
+        (WebCore::HTML5PreloadScanner::HTML5PreloadScanner):
+        (WebCore::HTML5PreloadScanner::processToken):
+        (WebCore::HTML5PreloadScanner::scanningBody):
+        * html/HTML5PreloadScanner.h:
+
 2010-06-17  Abhishek Arya  <inferno@chromium.org>
 
         Reviewed by David Kilzer.
index 49a1c8b..24c11ef 100644 (file)
@@ -1054,6 +1054,8 @@ webcore_sources += \
        WebCore/html/CollectionCache.cpp \
        WebCore/html/CollectionCache.h \
        WebCore/html/CollectionType.h \
+       WebCore/html/CSSPreloadScanner.cpp \
+       WebCore/html/CSSPreloadScanner.h \
        WebCore/html/DataGridColumn.cpp \
        WebCore/html/DataGridColumn.h \
        WebCore/html/DataGridColumnList.cpp \
index 0c0f580..6b7bb8a 100644 (file)
             'html/CollectionCache.cpp',
             'html/CollectionCache.h',
             'html/CollectionType.h',
+            'html/CSSPreloadScanner.cpp',
+            'html/CSSPreloadScanner.h',
             'html/DataGridColumn.cpp',
             'html/DataGridColumn.h',
             'html/DOMDataGridDataSource.cpp',
index 06da9a2..4b32e15 100644 (file)
@@ -598,6 +598,7 @@ SOURCES += \
     html/canvas/CanvasRenderingContext2D.cpp \
     html/canvas/CanvasStyle.cpp \
     html/CollectionCache.cpp \
+    html/CSSPreloadScanner.cpp \
     html/DataGridColumn.cpp \
     html/DataGridColumnList.cpp \
     html/DateComponents.cpp \
index 108895e..1dd3de2 100644 (file)
                                RelativePath="..\html\CollectionType.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\html\CSSPreloadScanner.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\html\CSSPreloadScanner.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\html\DataGridColumn.cpp"\r
                                >\r
index c64277d..58bd1eb 100644 (file)
                973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9738899F116EA9DC00ADF313 /* DocumentWriter.h */; settings = {ATTRIBUTES = (Private, ); }; };
                973E325610883B7C005BC493 /* ResourceLoadNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */; };
                973E325710883B7C005BC493 /* ResourceLoadNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 973E325510883B7C005BC493 /* ResourceLoadNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               976E2BA711CAE4DE006C56A0 /* CSSPreloadScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976E2BA511CAE4DE006C56A0 /* CSSPreloadScanner.cpp */; };
+               976E2BA811CAE4DE006C56A0 /* CSSPreloadScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 976E2BA611CAE4DE006C56A0 /* CSSPreloadScanner.h */; };
                976E896011C0CA3A00EA9CA9 /* HTML5EntityParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 976E895E11C0CA3A00EA9CA9 /* HTML5EntityParser.cpp */; };
                976E896111C0CA3A00EA9CA9 /* HTML5EntityParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 976E895F11C0CA3A00EA9CA9 /* HTML5EntityParser.h */; };
                979F43D31075E44A0000F83B /* RedirectScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 979F43D11075E44A0000F83B /* RedirectScheduler.cpp */; };
                9738899F116EA9DC00ADF313 /* DocumentWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentWriter.h; sourceTree = "<group>"; };
                973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadNotifier.cpp; sourceTree = "<group>"; };
                973E325510883B7C005BC493 /* ResourceLoadNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadNotifier.h; sourceTree = "<group>"; };
+               976E2BA511CAE4DE006C56A0 /* CSSPreloadScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPreloadScanner.cpp; sourceTree = "<group>"; };
+               976E2BA611CAE4DE006C56A0 /* CSSPreloadScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPreloadScanner.h; sourceTree = "<group>"; };
                976E895E11C0CA3A00EA9CA9 /* HTML5EntityParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTML5EntityParser.cpp; sourceTree = "<group>"; };
                976E895F11C0CA3A00EA9CA9 /* HTML5EntityParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5EntityParser.h; sourceTree = "<group>"; };
                979F43D11075E44A0000F83B /* RedirectScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RedirectScheduler.cpp; sourceTree = "<group>"; };
                                2ED609BA1145B07100C8684E /* DOMFormData.cpp */,
                                2ED609BB1145B07100C8684E /* DOMFormData.h */,
                                2E0888C3114883A900AF4265 /* DOMFormData.idl */,
+                               976E2BA511CAE4DE006C56A0 /* CSSPreloadScanner.cpp */,
+                               976E2BA611CAE4DE006C56A0 /* CSSPreloadScanner.h */,
                                BCDBB8CC0E08958400C60FF6 /* File.cpp */,
                                BCDBB8CB0E08958400C60FF6 /* File.h */,
                                BC1881D90E08C4ED00048C13 /* File.idl */,
                                816C80AF11BE990D009A45E9 /* JSIDBKeyRange.h in Headers */,
                                0853D73411C9109000B2FD42 /* SVGTextQuery.h in Headers */,
                                49FFBF3F11C93EE3006A7118 /* WebGLLayer.h in Headers */,
+                               976E2BA811CAE4DE006C56A0 /* CSSPreloadScanner.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                0853D73211C9109000B2FD42 /* SVGTextChunkLayoutInfo.cpp in Sources */,
                                0853D73311C9109000B2FD42 /* SVGTextQuery.cpp in Sources */,
                                49FFBF4011C93EE3006A7118 /* WebGLLayer.mm in Sources */,
+                               976E2BA711CAE4DE006C56A0 /* CSSPreloadScanner.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/WebCore/html/CSSPreloadScanner.cpp b/WebCore/html/CSSPreloadScanner.cpp
new file mode 100644 (file)
index 0000000..b2e933a
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CSSPreloadScanner.h"
+
+#include "CSSHelper.h"
+#include "CachedCSSStyleSheet.h"
+#include "DocLoader.h"
+#include "Document.h"
+#include "HTML5Token.h"
+
+namespace WebCore {
+
+static inline bool isWhitespace(UChar c)
+{
+    return c == ' ' || c == '\n' || c == '\r' || c == '\t';
+}
+
+CSSPreloadScanner::CSSPreloadScanner(Document* document)
+    : m_document(document)
+{
+    reset();
+}
+
+void CSSPreloadScanner::reset()
+{
+    m_state = Initial;
+    m_rule.clear();
+    m_ruleValue.clear();
+}
+
+void CSSPreloadScanner::scan(const HTML5Token& token, bool scanningBody)
+{
+    m_scanningBody = scanningBody;
+
+    const HTML5Token::DataVector& characters = token.characters();
+    for (HTML5Token::DataVector::const_iterator iter = characters.begin();
+         iter != characters.end(); ++iter) {
+        tokenize(*iter);
+    }
+}
+
+inline void CSSPreloadScanner::tokenize(UChar c)
+{
+    // We are just interested in @import rules, no need for real tokenization here
+    // Searching for other types of resources is probably low payoff.
+    switch (m_state) {
+    case Initial:
+        if (c == '@')
+            m_state = RuleStart;
+        else if (c == '/')
+            m_state = MaybeComment;
+        break;
+    case MaybeComment:
+        if (c == '*')
+            m_state = Comment;
+        else
+            m_state = Initial;
+        break;
+    case Comment:
+        if (c == '*')
+            m_state = MaybeCommentEnd;
+        break;
+    case MaybeCommentEnd:
+        if (c == '/')
+            m_state = Initial;
+        else if (c == '*')
+            ;
+        else
+            m_state = Comment;
+        break;
+    case RuleStart:
+        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
+            m_rule.clear();
+            m_ruleValue.clear();
+            m_rule.append(c);
+            m_state = Rule;
+        } else
+            m_state = Initial;
+        break;
+    case Rule:
+        if (isWhitespace(c))
+            m_state = AfterRule;
+        else if (c == ';')
+            m_state = Initial;
+        else
+            m_rule.append(c);
+        break;
+    case AfterRule:
+        if (isWhitespace(c))
+            ;
+        else if (c == ';')
+            m_state = Initial;
+        else {
+            m_state = RuleValue;
+            m_ruleValue.append(c);
+        }
+        break;
+    case RuleValue:
+        if (isWhitespace(c))
+            m_state = AfterRuleValue;
+        else if (c == ';') {
+            emitRule();
+            m_state = Initial;
+        } else 
+            m_ruleValue.append(c);
+        break;
+    case AfterRuleValue:
+        if (isWhitespace(c))
+            ;
+        else if (c == ';') {
+            emitRule();
+            m_state = Initial;
+        } else {
+            // FIXME: media rules
+            m_state = Initial;
+        }
+        break;
+    }
+}
+
+void CSSPreloadScanner::emitRule()
+{
+    String rule(m_rule.data(), m_rule.size());
+    if (equalIgnoringCase(rule, "import") && !m_ruleValue.isEmpty()) {
+        String value(m_ruleValue.data(), m_ruleValue.size());
+        String url = deprecatedParseURL(value);
+        if (!url.isEmpty())
+            m_document->docLoader()->preload(CachedResource::CSSStyleSheet, url, String(), m_scanningBody);
+    }
+    m_rule.clear();
+    m_ruleValue.clear();
+}
+
+}
diff --git a/WebCore/html/CSSPreloadScanner.h b/WebCore/html/CSSPreloadScanner.h
new file mode 100644 (file)
index 0000000..85ddaf6
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CSSPreloadScanner_h
+#define CSSPreloadScanner_h
+
+#include "PlatformString.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Document;
+class HTML5Token;
+
+class CSSPreloadScanner : public Noncopyable {
+public:
+    CSSPreloadScanner(Document*);
+
+    void reset();
+    void scan(const HTML5Token&, bool scanningBody);
+
+private:
+    enum State {
+        Initial,
+        MaybeComment,
+        Comment,
+        MaybeCommentEnd,
+        RuleStart,
+        Rule,
+        AfterRule,
+        RuleValue,
+        AfterRuleValue
+    };
+
+    inline void tokenize(UChar c);
+    void emitRule();
+
+    State m_state;
+    Vector<UChar, 16> m_rule;
+    Vector<UChar> m_ruleValue;
+
+    bool m_scanningBody;
+    Document* m_document;
+};
+
+}
+
+#endif
index 0fdc8f3..46527f4 100644 (file)
@@ -119,7 +119,9 @@ private:
 
 HTML5PreloadScanner::HTML5PreloadScanner(Document* document)
     : m_document(document)
+    , m_cssScanner(document)
     , m_bodySeen(false)
+    , m_inStyle(false)
 {
 }
 
@@ -140,6 +142,15 @@ void HTML5PreloadScanner::scan()
 
 void HTML5PreloadScanner::processToken()
 {
+    if (m_inStyle) {
+        if (m_token.type() == HTML5Token::Character)
+            m_cssScanner.scan(m_token, scanningBody());
+        else if (m_token.type() == HTML5Token::EndTag) {
+            m_inStyle = false;
+            m_cssScanner.reset();
+        }
+    }
+
     if (m_token.type() != HTML5Token::StartTag)
         return;
 
@@ -149,7 +160,15 @@ void HTML5PreloadScanner::processToken()
     if (task.tagName() == bodyTag)
         m_bodySeen = true;
 
-    task.preload(m_document, m_document->body() || m_bodySeen);
+    if (task.tagName() == styleTag)
+        m_inStyle = true;
+
+    task.preload(m_document, scanningBody());
+}
+
+bool HTML5PreloadScanner::scanningBody() const
+{
+    return m_document->body() || m_bodySeen;
 }
 
 }
index b3539b0..51be21a 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef HTML5PreloadScanner_h
 #define HTML5PreloadScanner_h
 
+#include "CSSPreloadScanner.h"
 #include "HTML5Lexer.h"
 #include "HTML5Token.h"
 #include "SegmentedString.h"
@@ -47,12 +48,15 @@ public:
 
 private:
     void processToken();
+    bool scanningBody() const;
 
     Document* m_document;
     SegmentedString m_source;
     HTML5Lexer m_lexer;
     HTML5Token m_token;
+    CSSPreloadScanner m_cssScanner;
     bool m_bodySeen;
+    bool m_inStyle;
 };
 
 }