Make the existing HTMLPreloadScanner threading-aware
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Feb 2013 05:14:03 +0000 (05:14 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Feb 2013 05:14:03 +0000 (05:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=107807

Reviewed by Adam Barth.

The HTMLPreloadScanner and CSSPreloadScanner do a number of things.
CSSPreloadScanner is mostly just a helper class for HTMLPreloadScanner.
HTMLPreloadScanner runs its own copy of the HTMLTokenizer and uses
HTMLTokenizer::updateStateFor to emulate enough of the TreeBuilder
to get a realistic stream of tokens.  It does some additional TreeBuilder
emulation, including tracking template tags and base tags, but mostly
just scans the token stream for start-tags and looks for URLs in them.
It tracks when it has seen a <style> tag and starts sending all character tokens
to the CSSPreloadScanner until a </style> tag is seen.
It also (unfortunately) knows some about the loader guts and how to construct
a proper CachedResourcRequest and issue a preload.

This patch changes the model so that the preload scanners only know how to produce
PreloadRequest objects and append them to a passed-in vector.

This changes the preload-scanner behavior so that preloads are now all issued in one large
batch at the end of scanning, instead of as we hit each resource.  It's possible that
we'll wait to instead check for preload requests more often, at a possible tradeoff
to tokenizing speed.

An alternate approach might be to pass in a preload-delegate of sorts which knew how
to either build a vector, or send requests immediately.  For now the build-a-vector-always
approach seems clean, and does not seem to slow down our PerformanceTest microbenchmarks at least.

This patch has 2 main pieces:
- Remove Document and (and loader) dependencies from HTMLPreloadScanner/CSSPreloadScanner
  This is done through introduction of a new HTMLResourcePreloader class which holds
  a Document* and knows how to talk to the CachedResourceLoader.
- Clean-up HTMLPreloadScanners token-loop to not be tied to having a Tokenizer.
  (On a background thead, the HTMLPreloadScanner won't own the tokenizer, it will just
   be passed in tokens and expected to issue loads if necessary.)

This passes all of the LayoutTests using the main thread parser.

This patch does not make the HTMLPreloadScanner 100% ready for threading
(it still uses AtomicString which is currently not-OK on the parser thread)
but it's very close.  Two further (already written) patches will complete this.

* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.xcodeproj/project.pbxproj:
* html/parser/CSSPreloadScanner.cpp:
(WebCore::CSSPreloadScanner::CSSPreloadScanner):
(WebCore::CSSPreloadScanner::scan):
(WebCore::CSSPreloadScanner::emitRule):
* html/parser/CSSPreloadScanner.h:
(CSSPreloadScanner):
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::HTMLDocumentParser):
(WebCore::HTMLDocumentParser::pumpTokenizer):
(WebCore::HTMLDocumentParser::insert):
(WebCore::HTMLDocumentParser::append):
(WebCore::HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan):
* html/parser/HTMLDocumentParser.h:
(HTMLDocumentParser):
* html/parser/HTMLPreloadScanner.cpp:
(WebCore::isStartTag):
(WebCore):
(WebCore::isStartOrEndTag):
(WebCore::PreloadTask::processAttributes):
(WebCore::PreloadTask::charset):
(PreloadTask):
(WebCore::PreloadTask::resourceType):
(WebCore::PreloadTask::shouldPreload):
(WebCore::PreloadTask::createPreloadRequest):
(WebCore::HTMLPreloadScanner::HTMLPreloadScanner):
(WebCore::HTMLPreloadScanner::scan):
(WebCore::HTMLPreloadScanner::processPossibleTemplateTag):
(WebCore::HTMLPreloadScanner::processPossibleStyleTag):
(WebCore::HTMLPreloadScanner::processPossibleBaseTag):
(WebCore::HTMLPreloadScanner::processToken):
* html/parser/HTMLPreloadScanner.h:
(HTMLPreloadScanner):
* html/parser/HTMLResourcePreloader.cpp: Added.
(WebCore):
(WebCore::isStringSafeToSendToAnotherThread):
(WebCore::PreloadRequest::isSafeToSendToAnotherThread):
(WebCore::PreloadRequest::completeURL):
(WebCore::PreloadRequest::resourceRequest):
(WebCore::HTMLResourcePreloader::preload):
* html/parser/HTMLResourcePreloader.h: Added.
(WebCore):
(PreloadRequest):
(WebCore::PreloadRequest::create):
(WebCore::PreloadRequest::PreloadRequest):
(HTMLResourcePreloader):
(WebCore::HTMLResourcePreloader::HTMLResourcePreloader):
(WebCore::HTMLResourcePreloader::createWeakPtr):
* loader/cache/CachedResourceRequest.h:

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

17 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/html/parser/CSSPreloadScanner.cpp
Source/WebCore/html/parser/CSSPreloadScanner.h
Source/WebCore/html/parser/HTMLDocumentParser.cpp
Source/WebCore/html/parser/HTMLDocumentParser.h
Source/WebCore/html/parser/HTMLPreloadScanner.cpp
Source/WebCore/html/parser/HTMLPreloadScanner.h
Source/WebCore/html/parser/HTMLResourcePreloader.cpp [new file with mode: 0644]
Source/WebCore/html/parser/HTMLResourcePreloader.h [new file with mode: 0644]
Source/WebCore/loader/cache/CachedResourceRequest.h

index ef3ac04..08d1565 100644 (file)
@@ -1563,6 +1563,7 @@ set(WebCore_SOURCES
     html/parser/HTMLFormattingElementList.cpp
     html/parser/HTMLMetaCharsetParser.cpp
     html/parser/HTMLPreloadScanner.cpp
+    html/parser/HTMLResourcePreloader.cpp
     html/parser/HTMLScriptRunner.cpp
     html/parser/HTMLSourceTracker.cpp
     html/parser/HTMLTokenizer.cpp
index 3d08dd6..ce7770d 100644 (file)
@@ -1,3 +1,104 @@
+2013-02-10  Eric Seidel  <eric@webkit.org>
+
+        Make the existing HTMLPreloadScanner threading-aware
+        https://bugs.webkit.org/show_bug.cgi?id=107807
+
+        Reviewed by Adam Barth.
+
+        The HTMLPreloadScanner and CSSPreloadScanner do a number of things.
+        CSSPreloadScanner is mostly just a helper class for HTMLPreloadScanner.
+        HTMLPreloadScanner runs its own copy of the HTMLTokenizer and uses
+        HTMLTokenizer::updateStateFor to emulate enough of the TreeBuilder
+        to get a realistic stream of tokens.  It does some additional TreeBuilder
+        emulation, including tracking template tags and base tags, but mostly
+        just scans the token stream for start-tags and looks for URLs in them.
+        It tracks when it has seen a <style> tag and starts sending all character tokens
+        to the CSSPreloadScanner until a </style> tag is seen.
+        It also (unfortunately) knows some about the loader guts and how to construct
+        a proper CachedResourcRequest and issue a preload.
+
+        This patch changes the model so that the preload scanners only know how to produce
+        PreloadRequest objects and append them to a passed-in vector.
+
+        This changes the preload-scanner behavior so that preloads are now all issued in one large
+        batch at the end of scanning, instead of as we hit each resource.  It's possible that
+        we'll wait to instead check for preload requests more often, at a possible tradeoff
+        to tokenizing speed.
+
+        An alternate approach might be to pass in a preload-delegate of sorts which knew how
+        to either build a vector, or send requests immediately.  For now the build-a-vector-always
+        approach seems clean, and does not seem to slow down our PerformanceTest microbenchmarks at least.
+
+        This patch has 2 main pieces:
+        - Remove Document and (and loader) dependencies from HTMLPreloadScanner/CSSPreloadScanner
+          This is done through introduction of a new HTMLResourcePreloader class which holds
+          a Document* and knows how to talk to the CachedResourceLoader.
+        - Clean-up HTMLPreloadScanners token-loop to not be tied to having a Tokenizer.
+          (On a background thead, the HTMLPreloadScanner won't own the tokenizer, it will just
+           be passed in tokens and expected to issue loads if necessary.)
+
+        This passes all of the LayoutTests using the main thread parser.
+
+        This patch does not make the HTMLPreloadScanner 100% ready for threading
+        (it still uses AtomicString which is currently not-OK on the parser thread)
+        but it's very close.  Two further (already written) patches will complete this.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * html/parser/CSSPreloadScanner.cpp:
+        (WebCore::CSSPreloadScanner::CSSPreloadScanner):
+        (WebCore::CSSPreloadScanner::scan):
+        (WebCore::CSSPreloadScanner::emitRule):
+        * html/parser/CSSPreloadScanner.h:
+        (CSSPreloadScanner):
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::HTMLDocumentParser):
+        (WebCore::HTMLDocumentParser::pumpTokenizer):
+        (WebCore::HTMLDocumentParser::insert):
+        (WebCore::HTMLDocumentParser::append):
+        (WebCore::HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan):
+        * html/parser/HTMLDocumentParser.h:
+        (HTMLDocumentParser):
+        * html/parser/HTMLPreloadScanner.cpp:
+        (WebCore::isStartTag):
+        (WebCore):
+        (WebCore::isStartOrEndTag):
+        (WebCore::PreloadTask::processAttributes):
+        (WebCore::PreloadTask::charset):
+        (PreloadTask):
+        (WebCore::PreloadTask::resourceType):
+        (WebCore::PreloadTask::shouldPreload):
+        (WebCore::PreloadTask::createPreloadRequest):
+        (WebCore::HTMLPreloadScanner::HTMLPreloadScanner):
+        (WebCore::HTMLPreloadScanner::scan):
+        (WebCore::HTMLPreloadScanner::processPossibleTemplateTag):
+        (WebCore::HTMLPreloadScanner::processPossibleStyleTag):
+        (WebCore::HTMLPreloadScanner::processPossibleBaseTag):
+        (WebCore::HTMLPreloadScanner::processToken):
+        * html/parser/HTMLPreloadScanner.h:
+        (HTMLPreloadScanner):
+        * html/parser/HTMLResourcePreloader.cpp: Added.
+        (WebCore):
+        (WebCore::isStringSafeToSendToAnotherThread):
+        (WebCore::PreloadRequest::isSafeToSendToAnotherThread):
+        (WebCore::PreloadRequest::completeURL):
+        (WebCore::PreloadRequest::resourceRequest):
+        (WebCore::HTMLResourcePreloader::preload):
+        * html/parser/HTMLResourcePreloader.h: Added.
+        (WebCore):
+        (PreloadRequest):
+        (WebCore::PreloadRequest::create):
+        (WebCore::PreloadRequest::PreloadRequest):
+        (HTMLResourcePreloader):
+        (WebCore::HTMLResourcePreloader::HTMLResourcePreloader):
+        (WebCore::HTMLResourcePreloader::createWeakPtr):
+        * loader/cache/CachedResourceRequest.h:
+
 2013-02-06  Kentaro Hara  <haraken@chromium.org>
 
         [V8] Rename isolated() to getWorld(), rename worldForEnteredContextIfIsolated() to worldForEnteredContext()
index ed3cadf..725643b 100644 (file)
@@ -3602,6 +3602,8 @@ webcore_sources += \
        Source/WebCore/html/parser/HTMLParserThread.h \
        Source/WebCore/html/parser/HTMLPreloadScanner.cpp \
        Source/WebCore/html/parser/HTMLPreloadScanner.h \
+       Source/WebCore/html/parser/HTMLResourcePreloader.cpp \
+       Source/WebCore/html/parser/HTMLResourcePreloader.h \
        Source/WebCore/html/parser/HTMLScriptRunner.cpp \
        Source/WebCore/html/parser/HTMLScriptRunner.h \
        Source/WebCore/html/parser/HTMLScriptRunnerHost.h \
index 53e0ddd..97cdd0b 100644 (file)
@@ -740,6 +740,7 @@ SOURCES += \
     html/parser/HTMLParserScheduler.cpp \
     html/parser/HTMLParserThread.cpp \
     html/parser/HTMLPreloadScanner.cpp \
+    html/parser/HTMLResourcePreloader.cpp \
     html/parser/HTMLScriptRunner.cpp \
     html/parser/HTMLSourceTracker.cpp \
     html/parser/HTMLTokenizer.cpp \
@@ -1925,6 +1926,7 @@ HEADERS += \
     html/parser/HTMLFormattingElementList.h \
     html/parser/HTMLParserScheduler.h \
     html/parser/HTMLPreloadScanner.h \
+    html/parser/HTMLResourcePreloader.h \
     html/parser/HTMLScriptRunner.h \
     html/parser/HTMLScriptRunnerHost.h \
     html/parser/HTMLToken.h \
index 6f33a80..2885f07 100644 (file)
             'html/parser/HTMLParserThread.h',
             'html/parser/HTMLPreloadScanner.cpp',
             'html/parser/HTMLPreloadScanner.h',
+            'html/parser/HTMLResourcePreloader.cpp',
+            'html/parser/HTMLResourcePreloader.h',
             'html/parser/HTMLScriptRunner.cpp',
             'html/parser/HTMLScriptRunner.h',
             'html/parser/HTMLScriptRunnerHost.h',
index f695c2c..3ec67eb 100755 (executable)
                                        >
                                </File>
                                <File
+                                       RelativePath="..\html\parser\HTMLResourcePreloader.cpp"
+                                       >
+                               </File>
+                               <File
+                                       RelativePath="..\html\parser\HTMLResourcePreloader.h"
+                                       >
+                               </File>
+                               <File
                                        RelativePath="..\html\parser\HTMLScriptRunner.cpp"
                                        >
                                </File>
index 27a3eda..2a2f369 100644 (file)
     <ClCompile Include="..\html\parser\HTMLParserScheduler.cpp" />
     <ClCompile Include="..\html\parser\HTMLParserThread.cpp" />
     <ClCompile Include="..\html\parser\HTMLPreloadScanner.cpp" />
+    <ClCompile Include="..\html\parser\HTMLResourcePreloader.cpp" />
     <ClCompile Include="..\html\parser\HTMLScriptRunner.cpp" />
     <ClCompile Include="..\html\parser\HTMLSourceTracker.cpp" />
     <ClCompile Include="..\html\parser\HTMLTokenizer.cpp" />
     <ClInclude Include="..\html\parser\HTMLParserScheduler.h" />
     <ClInclude Include="..\html\parser\HTMLParserThread.h" />
     <ClInclude Include="..\html\parser\HTMLPreloadScanner.h" />
+    <ClInclude Include="..\html\parser\HTMLResourcePreloader.h" />
     <ClInclude Include="..\html\parser\HTMLScriptRunner.h" />
     <ClInclude Include="..\html\parser\HTMLScriptRunnerHost.h" />
     <ClInclude Include="..\html\parser\HTMLSourceTracker.h" />
index f087b6e..16a78e0 100644 (file)
                A8D065AE0A2446CD005E7203 /* JSHTMLFormElementCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8D065AD0A2446CD005E7203 /* JSHTMLFormElementCustom.cpp */; };
                A8D06B390A265DCD005E7203 /* HTMLNames.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = A8D06B370A265DCD005E7203 /* HTMLNames.h */; settings = {ATTRIBUTES = (); }; };
                A8D06B3A0A265DCD005E7203 /* HTMLNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8D06B380A265DCD005E7203 /* HTMLNames.cpp */; };
+               A8D223FD16B52E4E00157288 /* HTMLResourcePreloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8D223FB16B52E4E00157288 /* HTMLResourcePreloader.cpp */; };
+               A8D223FE16B52E4E00157288 /* HTMLResourcePreloader.h in Headers */ = {isa = PBXBuildFile; fileRef = A8D223FC16B52E4E00157288 /* HTMLResourcePreloader.h */; };
                A8DF3FCE097FA0FC0052981B /* HTMLFormControlsCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = A8DF3FC6097FA0FB0052981B /* HTMLFormControlsCollection.h */; };
                A8DF3FCF097FA0FC0052981B /* HTMLFormControlsCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DF3FC7097FA0FB0052981B /* HTMLFormControlsCollection.cpp */; };
                A8DF3FD0097FA0FC0052981B /* HTMLCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = A8DF3FC8097FA0FB0052981B /* HTMLCollection.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A8D065AD0A2446CD005E7203 /* JSHTMLFormElementCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLFormElementCustom.cpp; sourceTree = "<group>"; };
                A8D06B370A265DCD005E7203 /* HTMLNames.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLNames.h; sourceTree = "<group>"; };
                A8D06B380A265DCD005E7203 /* HTMLNames.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLNames.cpp; sourceTree = "<group>"; };
+               A8D223FB16B52E4E00157288 /* HTMLResourcePreloader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLResourcePreloader.cpp; path = parser/HTMLResourcePreloader.cpp; sourceTree = "<group>"; };
+               A8D223FC16B52E4E00157288 /* HTMLResourcePreloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLResourcePreloader.h; path = parser/HTMLResourcePreloader.h; sourceTree = "<group>"; };
                A8DF3FC6097FA0FB0052981B /* HTMLFormControlsCollection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLFormControlsCollection.h; sourceTree = "<group>"; };
                A8DF3FC7097FA0FB0052981B /* HTMLFormControlsCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLFormControlsCollection.cpp; sourceTree = "<group>"; };
                A8DF3FC8097FA0FB0052981B /* HTMLCollection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLCollection.h; sourceTree = "<group>"; };
                                974187D116A7932200FA77A7 /* HTMLParserThread.h */,
                                977B3859122883E900B81FF8 /* HTMLPreloadScanner.cpp */,
                                977B385A122883E900B81FF8 /* HTMLPreloadScanner.h */,
+                               A8D223FB16B52E4E00157288 /* HTMLResourcePreloader.cpp */,
+                               A8D223FC16B52E4E00157288 /* HTMLResourcePreloader.h */,
                                977B385B122883E900B81FF8 /* HTMLScriptRunner.cpp */,
                                977B385C122883E900B81FF8 /* HTMLScriptRunner.h */,
                                977B385D122883E900B81FF8 /* HTMLScriptRunnerHost.h */,
                                A43BF5991149290A00C643CA /* HTMLProgressElement.h in Headers */,
                                033A6A7C147E07D200509B36 /* HTMLPropertiesCollection.h in Headers */,
                                A8CFF7A30A156978000A4234 /* HTMLQuoteElement.h in Headers */,
+                               A8D223FE16B52E4E00157288 /* HTMLResourcePreloader.h in Headers */,
                                A871DC250A15205700B12A68 /* HTMLScriptElement.h in Headers */,
                                977B3875122883E900B81FF8 /* HTMLScriptRunner.h in Headers */,
                                977B3876122883E900B81FF8 /* HTMLScriptRunnerHost.h in Headers */,
                                A43BF5981149290A00C643CA /* HTMLProgressElement.cpp in Sources */,
                                033A6A7E147E07E700509B36 /* HTMLPropertiesCollection.cpp in Sources */,
                                A8CFF7A50A156978000A4234 /* HTMLQuoteElement.cpp in Sources */,
+                               A8D223FD16B52E4E00157288 /* HTMLResourcePreloader.cpp in Sources */,
                                A871DC220A15205700B12A68 /* HTMLScriptElement.cpp in Sources */,
                                977B3874122883E900B81FF8 /* HTMLScriptRunner.cpp in Sources */,
                                A81369D9097374F600D74463 /* HTMLSelectElement.cpp in Sources */,
index 8eec81b..3bfe816 100644 (file)
 #include "CachedResourceLoader.h"
 #include "CachedResourceRequest.h"
 #include "CachedResourceRequestInitiators.h"
-#include "Document.h"
 #include "HTMLParserIdioms.h"
 #include "HTMLToken.h"
+#include <wtf/Functional.h>
+#include <wtf/MainThread.h>
 
 namespace WebCore {
 
-CSSPreloadScanner::CSSPreloadScanner(Document* document)
+CSSPreloadScanner::CSSPreloadScanner()
     : m_state(Initial)
-    , m_document(document)
+    , m_requests(0)
 {
 }
 
@@ -51,11 +52,13 @@ void CSSPreloadScanner::reset()
     m_ruleValue.clear();
 }
 
-void CSSPreloadScanner::scan(const HTMLToken& token)
+void CSSPreloadScanner::scan(const HTMLToken& token, Vector<OwnPtr<PreloadRequest> >& requests)
 {
+    m_requests = &requests;
     const HTMLToken::DataVector& characters = token.characters();
     for (HTMLToken::DataVector::const_iterator iter = characters.begin(); iter != characters.end() && m_state != DoneParsingImportRules; ++iter)
         tokenize(*iter);
+    m_requests = 0;
 }
 
 inline void CSSPreloadScanner::tokenize(UChar c)
@@ -193,11 +196,13 @@ static String parseCSSStringOrURL(const UChar* characters, size_t length)
 void CSSPreloadScanner::emitRule()
 {
     if (equalIgnoringCase("import", m_rule.characters(), m_rule.length())) {
-        String value = parseCSSStringOrURL(m_ruleValue.characters(), m_ruleValue.length());
-        if (!value.isEmpty()) {
-            CachedResourceRequest request(ResourceRequest(m_document->completeURL(value)));
-            request.setInitiator(cachedResourceRequestInitiators().css);
-            m_document->cachedResourceLoader()->preload(CachedResource::CSSStyleSheet, request, String());
+        String url = parseCSSStringOrURL(m_ruleValue.characters(), m_ruleValue.length());
+        if (!url.isEmpty()) {
+            KURL baseElementURL; // FIXME: This should be passed in from the HTMLPreloadScaner via scan()!
+            OwnPtr<PreloadRequest> request = PreloadRequest::create(
+                cachedResourceRequestInitiators().css, url, baseElementURL, CachedResource::CSSStyleSheet);
+            // FIXME: Should this be including the charset in the preload request?
+            m_requests->append(request.release());
         }
         m_state = Initial;
     } else if (equalIgnoringCase("charset", m_rule.characters(), m_rule.length()))
index 8e19296..ff9496f 100644 (file)
 #ifndef CSSPreloadScanner_h
 #define CSSPreloadScanner_h
 
+#include "HTMLResourcePreloader.h"
+#include <wtf/WeakPtr.h>
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
-class Document;
 class HTMLToken;
 
 class CSSPreloadScanner {
     WTF_MAKE_NONCOPYABLE(CSSPreloadScanner);
 public:
-    explicit CSSPreloadScanner(Document*);
+    explicit CSSPreloadScanner();
 
     void reset();
-    void scan(const HTMLToken&);
+    void scan(const HTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
 
 private:
     enum State {
@@ -56,14 +57,15 @@ private:
         DoneParsingImportRules,
     };
 
-    inline void tokenize(UChar c);
+    inline void tokenize(UChar);
     void emitRule();
 
     State m_state;
     StringBuilder m_rule;
     StringBuilder m_ruleValue;
 
-    Document* m_document;
+    // Only non-zero during scan()
+    Vector<OwnPtr<PreloadRequest> >* m_requests;
 };
 
 }
index 870e034..a9c0927 100644 (file)
@@ -87,6 +87,7 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
 #if ENABLE(THREADED_HTML_PARSER)
     , m_weakFactory(this)
 #endif
+    , m_preloader(adoptPtr(new HTMLResourcePreloader(document)))
     , m_endWasDelayed(false)
     , m_haveBackgroundParser(false)
     , m_pumpSessionNestingLevel(0)
@@ -434,10 +435,10 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
     if (isWaitingForScripts()) {
         ASSERT(m_tokenizer->state() == HTMLTokenizerState::DataState);
         if (!m_preloadScanner) {
-            m_preloadScanner = adoptPtr(new HTMLPreloadScanner(document(), m_options));
+            m_preloadScanner = adoptPtr(new HTMLPreloadScanner(m_options, document()->url()));
             m_preloadScanner->appendToEnd(m_input.current());
         }
-        m_preloadScanner->scan();
+        m_preloadScanner->scan(m_preloader.get(), document()->baseElementURL());
     }
 
     InspectorInstrumentation::didWriteHTML(cookie, m_input.current().currentLine().zeroBasedInt());
@@ -521,9 +522,9 @@ void HTMLDocumentParser::insert(const SegmentedString& source)
         // Check the document.write() output with a separate preload scanner as
         // the main scanner can't deal with insertions.
         if (!m_insertionPreloadScanner)
-            m_insertionPreloadScanner = adoptPtr(new HTMLPreloadScanner(document(), m_options));
+            m_insertionPreloadScanner = adoptPtr(new HTMLPreloadScanner(m_options, document()->url()));
         m_insertionPreloadScanner->appendToEnd(source);
-        m_insertionPreloadScanner->scan();
+        m_insertionPreloadScanner->scan(m_preloader.get(), document()->baseElementURL());
     }
 
     endIfDelayed();
@@ -587,7 +588,7 @@ void HTMLDocumentParser::append(const SegmentedString& source)
         } else {
             m_preloadScanner->appendToEnd(source);
             if (isWaitingForScripts())
-                m_preloadScanner->scan();
+                m_preloadScanner->scan(m_preloader.get(), document()->baseElementURL());
         }
     }
 
@@ -774,7 +775,7 @@ void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan()
 {
     ASSERT(m_preloadScanner);
     m_preloadScanner->appendToEnd(m_input.current());
-    m_preloadScanner->scan();
+    m_preloadScanner->scan(m_preloader.get(), document()->baseElementURL());
 }
 
 void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource)
index 0f6a2e5..0207cc9 100644 (file)
@@ -56,6 +56,7 @@ class HTMLTokenizer;
 class HTMLScriptRunner;
 class HTMLTreeBuilder;
 class HTMLPreloadScanner;
+class HTMLResourcePreloader;
 class ScriptController;
 class ScriptSourceCode;
 
@@ -189,6 +190,7 @@ private:
     WeakPtrFactory<HTMLDocumentParser> m_weakFactory;
     WeakPtr<BackgroundHTMLParser> m_backgroundParser;
 #endif
+    OwnPtr<HTMLResourcePreloader> m_preloader;
 
     bool m_endWasDelayed;
     bool m_haveBackgroundParser;
index ec7e7d2..9fdd145 100644 (file)
 #include "config.h"
 #include "HTMLPreloadScanner.h"
 
-#include "CachedResourceLoader.h"
-#include "Document.h"
-#include "HTMLDocumentParser.h"
-#include "HTMLTokenizer.h"
 #include "HTMLNames.h"
 #include "HTMLParserIdioms.h"
 #include "HTMLParserOptions.h"
+#include "HTMLTokenizer.h"
 #include "InputTypeNames.h"
 #include "LinkRelAttribute.h"
 #include "MediaList.h"
 #include "MediaQueryEvaluator.h"
+#include <wtf/Functional.h>
+#include <wtf/MainThread.h>
 
 namespace WebCore {
 
 using namespace HTMLNames;
 
+static bool isStartTag(const HTMLToken& token)
+{
+    return token.type() == HTMLTokenTypes::StartTag;
+}
+
+static bool isStartOrEndTag(const HTMLToken& token)
+{
+    return token.type() == HTMLTokenTypes::EndTag || isStartTag(token);
+}
+
 class PreloadTask {
 public:
     explicit PreloadTask(const AtomicString& tagName, const HTMLToken::AttributeList& attributes)
@@ -89,9 +98,6 @@ public:
                     setUrlToLoad(attributeValue);
                 else if (attributeName == typeAttr)
                     m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image());
-            } else if (m_tagName == baseTag) {
-                if (attributeName == hrefAttr)
-                    m_baseElementHref = stripLeadingAndTrailingHTMLSpaces(attributeValue);
             }
         }
     }
@@ -124,26 +130,51 @@ public:
         m_urlToLoad = stripLeadingAndTrailingHTMLSpaces(attributeValue);
     }
 
-    void preload(Document* document, const KURL& baseURL)
+    const String& charset() const
+    {
+        // FIXME: Its not clear that this if is needed, the loader probably ignores charset for image requests anyway.
+        if (m_tagName == imgTag)
+            return emptyString();
+        return m_charset;
+    }
+
+    CachedResource::Type resourceType() const
+    {
+        if (m_tagName == scriptTag)
+            return CachedResource::Script;
+        if (m_tagName == imgTag || (m_tagName == inputTag && m_inputIsImage))
+            return CachedResource::ImageResource;
+        if (m_tagName == linkTag && m_linkIsStyleSheet && m_linkMediaAttributeIsScreen)
+            return CachedResource::CSSStyleSheet;
+        ASSERT_NOT_REACHED();
+        return CachedResource::RawResource;
+    }
+
+    bool shouldPreload()
     {
         if (m_urlToLoad.isEmpty())
-            return;
+            return false;
 
-        CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
-        CachedResourceRequest request(ResourceRequest(document->completeURL(m_urlToLoad, baseURL)));
-        request.setInitiator(tagName());
-        if (m_tagName == scriptTag) {
-            request.mutableResourceRequest().setAllowCookies(crossOriginModeAllowsCookies());
-            cachedResourceLoader->preload(CachedResource::Script, request, m_charset);
-        }
-        else if (m_tagName == imgTag || (m_tagName == inputTag && m_inputIsImage))
-            cachedResourceLoader->preload(CachedResource::ImageResource, request, String());
-        else if (m_tagName == linkTag && m_linkIsStyleSheet && m_linkMediaAttributeIsScreen) 
-            cachedResourceLoader->preload(CachedResource::CSSStyleSheet, request, m_charset);
+        if (m_tagName == linkTag && (!m_linkIsStyleSheet || !m_linkMediaAttributeIsScreen))
+            return false;
+
+        if (m_tagName == inputTag && !m_inputIsImage)
+            return false;
+        return true;
+    }
+
+    PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL)
+    {
+        if (!shouldPreload())
+            return nullptr;
+
+        OwnPtr<PreloadRequest> request = PreloadRequest::create(m_tagName, m_urlToLoad, predictedBaseURL, resourceType());
+        request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies());
+        request->setCharset(charset());
+        return request.release();
     }
 
     const AtomicString& tagName() const { return m_tagName; }
-    const String& baseElementHref() const { return m_baseElementHref; }
 
 private:
 
@@ -155,18 +186,16 @@ private:
     AtomicString m_tagName;
     String m_urlToLoad;
     String m_charset;
-    String m_baseElementHref;
     String m_crossOriginMode;
     bool m_linkIsStyleSheet;
     bool m_linkMediaAttributeIsScreen;
     bool m_inputIsImage;
 };
 
-HTMLPreloadScanner::HTMLPreloadScanner(Document* document, const HTMLParserOptions& options)
-    : m_document(document)
-    , m_cssScanner(document)
-    , m_tokenizer(HTMLTokenizer::create(options))
+HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const KURL& documentURL)
+    : m_tokenizer(HTMLTokenizer::create(options))
     , m_inStyle(false)
+    , m_documentURL(documentURL)
 #if ENABLE(TEMPLATE_ELEMENT)
     , m_templateCount(0)
 #endif
@@ -178,66 +207,102 @@ void HTMLPreloadScanner::appendToEnd(const SegmentedString& source)
     m_source.append(source);
 }
 
-void HTMLPreloadScanner::scan()
+// This function exists for convenience on the main thread and is not used by the background-thread preload scanner.
+void HTMLPreloadScanner::scan(HTMLResourcePreloader* preloader, const KURL& startingBaseElementURL)
 {
+    ASSERT(isMainThread()); // HTMLTokenizer::updateStateFor only works on the main thread.
     // When we start scanning, our best prediction of the baseElementURL is the real one!
-    m_predictedBaseElementURL = m_document->baseElementURL();
+    if (!startingBaseElementURL.isEmpty())
+        m_predictedBaseElementURL = startingBaseElementURL;
 
-    // FIXME: We should save and re-use these tokens in HTMLDocumentParser if
-    // the pending script doesn't end up calling document.write.
+    Vector<OwnPtr<PreloadRequest> > requests;
+    // Note: m_token is only used from this function and for the main thread.
+    // All other functions are passed a token.
     while (m_tokenizer->nextToken(m_source, m_token)) {
-        processToken();
+        if (isStartTag(m_token))
+            m_tokenizer->updateStateFor(AtomicString(m_token.name().data(), m_token.name().size()));
+        processToken(m_token, requests);
         m_token.clear();
     }
+    for (size_t i = 0; i < requests.size(); i++)
+        preloader->preload(requests[i].release());
 }
 
-void HTMLPreloadScanner::processToken()
-{
-    if (m_inStyle) {
-        if (m_token.type() == HTMLTokenTypes::Character)
-            m_cssScanner.scan(m_token);
-        else if (m_token.type() == HTMLTokenTypes::EndTag) {
-            m_inStyle = false;
-            m_cssScanner.reset();
-        }
-    }
-
-    if (m_token.type() != HTMLTokenTypes::StartTag) {
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (m_templateCount && m_token.type() == HTMLTokenTypes::EndTag && AtomicString(m_token.name().data(), m_token.name().size()) == templateTag)
+bool HTMLPreloadScanner::processPossibleTemplateTag(const AtomicString& tagName, const HTMLToken& token)
+{
+    if (isStartOrEndTag(token) && tagName == templateTag) {
+        if (isStartTag(token))
+            m_templateCount++;
+        else
             m_templateCount--;
-#endif
-        return;
+        return true; // Twas our token.
     }
-
-    AtomicString tagName(m_token.name().data(), m_token.name().size());
-
-#if ENABLE(TEMPLATE_ELEMENT)
-    if (tagName == templateTag)
-        m_templateCount++;
-
-    if (m_templateCount)
-        return;
+    // If we're in a template we "consume" all tokens.
+    return m_templateCount > 0;
+}
 #endif
 
-    PreloadTask task(tagName, m_token.attributes());
-    m_tokenizer->updateStateFor(task.tagName());
-
-    if (task.tagName() == styleTag)
-        m_inStyle = true;
+bool HTMLPreloadScanner::processPossibleStyleTag(const AtomicString& tagName, const HTMLToken& token)
+{
+    ASSERT(isStartOrEndTag(token));
+    if (tagName == styleTag) {
+        m_inStyle = isStartTag(token);
+        if (!m_inStyle)
+            m_cssScanner.reset();
+        return true;
+    }
+    return false;
+}
 
-    if (task.tagName() == baseTag)
-        updatePredictedBaseElementURL(KURL(m_document->url(), task.baseElementHref()));
+bool HTMLPreloadScanner::processPossibleBaseTag(const AtomicString& tagName, const HTMLToken& token)
+{
+    ASSERT(isStartTag(token));
+    if (tagName == baseTag) {
+        // The first <base> element is the one that wins.
+        if (!m_predictedBaseElementURL.isEmpty())
+            return true;
 
-    task.preload(m_document, m_predictedBaseElementURL.isEmpty() ? m_document->baseURL() : m_predictedBaseElementURL);
+        for (HTMLToken::AttributeList::const_iterator iter = token.attributes().begin(); iter != token.attributes().end(); ++iter) {
+            AtomicString attributeName(iter->m_name.data(), iter->m_name.size());
+            if (attributeName == hrefAttr) {
+                String hrefValue = StringImpl::create8BitIfPossible(iter->m_value.data(), iter->m_value.size());
+                m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefValue));
+                break;
+            }
+        }
+        return true;
+    }
+    return false;
 }
 
-void HTMLPreloadScanner::updatePredictedBaseElementURL(const KURL& baseElementURL)
+void HTMLPreloadScanner::processToken(const HTMLToken& token, Vector<OwnPtr<PreloadRequest> >& requests)
 {
-    // The first <base> element is the one that wins.
-    if (!m_predictedBaseElementURL.isEmpty())
+    // <style> is the only place we search for urls in non-start/end-tag tokens.
+    if (m_inStyle) {
+        if (token.type() != HTMLTokenTypes::Character)
+            return;
+        return m_cssScanner.scan(token, requests);
+    }
+    if (!isStartOrEndTag(token))
+        return;
+
+    AtomicString tagName(token.name().data(), token.name().size());
+#if ENABLE(TEMPLATE_ELEMENT)
+    if (processPossibleTemplateTag(tagName, token))
+        return;
+#endif
+    if (processPossibleStyleTag(tagName, token))
         return;
-    m_predictedBaseElementURL = baseElementURL;
+    if (!isStartTag(token))
+        return;
+    if (processPossibleBaseTag(tagName, token))
+        return;
+
+    PreloadTask task(tagName, token.attributes());
+    OwnPtr<PreloadRequest> request =  task.createPreloadRequest(m_predictedBaseElementURL);
+    if (request)
+        requests.append(request.release());
 }
 
 }
index cb8f339..90ff1c5 100644 (file)
@@ -33,7 +33,6 @@
 
 namespace WebCore {
 
-class Document;
 class HTMLParserOptions;
 class HTMLToken;
 class HTMLTokenizer;
@@ -42,21 +41,30 @@ class SegmentedString;
 class HTMLPreloadScanner {
     WTF_MAKE_NONCOPYABLE(HTMLPreloadScanner); WTF_MAKE_FAST_ALLOCATED;
 public:
-    HTMLPreloadScanner(Document*, const HTMLParserOptions&);
+    // HTMLPreloadScanner intentionally does not have a pointer to Document.
+    HTMLPreloadScanner(const HTMLParserOptions&, const KURL& documentURL);
 
     void appendToEnd(const SegmentedString&);
-    void scan();
+    void scan(HTMLResourcePreloader*, const KURL& documentBaseElementURL);
 
 private:
-    void processToken();
-    void updatePredictedBaseElementURL(const KURL& baseElementURL);
+    void processToken(const HTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
+
+    bool processStyleCharacters(const HTMLToken&);
+
+#if ENABLE(TEMPLATE_ELEMENT)
+    bool processPossibleTemplateTag(const AtomicString& tagName, const HTMLToken&);
+#endif
+
+    bool processPossibleStyleTag(const AtomicString& tagName, const HTMLToken&);
+    bool processPossibleBaseTag(const AtomicString& tagName, const HTMLToken&);
 
-    Document* m_document;
     SegmentedString m_source;
     CSSPreloadScanner m_cssScanner;
-    OwnPtr<HTMLTokenizer> m_tokenizer;
     HTMLToken m_token;
+    OwnPtr<HTMLTokenizer> m_tokenizer;
     bool m_inStyle;
+    KURL m_documentURL;
     KURL m_predictedBaseElementURL;
 
 #if ENABLE(TEMPLATE_ELEMENT)
diff --git a/Source/WebCore/html/parser/HTMLResourcePreloader.cpp b/Source/WebCore/html/parser/HTMLResourcePreloader.cpp
new file mode 100644 (file)
index 0000000..1519d20
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 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 "HTMLResourcePreloader.h"
+
+#include "CachedResourceLoader.h"
+#include "Document.h"
+
+namespace WebCore {
+
+static bool isStringSafeToSendToAnotherThread(const String& string)
+{
+    StringImpl* impl = string.impl();
+    if (!impl)
+        return true;
+    if (impl->hasOneRef())
+        return true;
+    if (string.isEmpty())
+        return true;
+    return false;
+}
+
+bool PreloadRequest::isSafeToSendToAnotherThread() const
+{
+    return isStringSafeToSendToAnotherThread(m_initiator)
+        && isStringSafeToSendToAnotherThread(m_charset)
+        && isStringSafeToSendToAnotherThread(m_resourceURL)
+        && isStringSafeToSendToAnotherThread(m_baseURL.string());
+}
+
+KURL PreloadRequest::completeURL(Document* document)
+{
+    return document->completeURL(m_resourceURL, m_baseURL.isEmpty() ? document->url() : m_baseURL);
+}
+
+CachedResourceRequest PreloadRequest::resourceRequest(Document* document)
+{
+    ASSERT(isMainThread());
+    CachedResourceRequest request(ResourceRequest(completeURL(document)));
+    request.setInitiator(m_initiator);
+
+    // FIXME: It's possible CORS should work for other request types?
+    if (m_resourceType == CachedResource::Script)
+        request.mutableResourceRequest().setAllowCookies(m_crossOriginModeAllowsCookies);
+    return request;
+}
+
+void HTMLResourcePreloader::preload(PassOwnPtr<PreloadRequest> preload)
+{
+    CachedResourceRequest request = preload->resourceRequest(m_document);
+    m_document->cachedResourceLoader()->preload(preload->resourceType(), request, preload->charset());
+}
+
+}
diff --git a/Source/WebCore/html/parser/HTMLResourcePreloader.h b/Source/WebCore/html/parser/HTMLResourcePreloader.h
new file mode 100644 (file)
index 0000000..c02a250
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 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 HTMLResourcePreloader_h
+#define HTMLResourcePreloader_h
+
+#include "CachedResource.h"
+#include "CachedResourceRequest.h"
+
+namespace WebCore {
+
+class PreloadRequest {
+public:
+    static PassOwnPtr<PreloadRequest> create(const String& initiator, const String& resourceURL, const KURL& baseURL, CachedResource::Type resourceType)
+    {
+        return adoptPtr(new PreloadRequest(initiator, resourceURL, baseURL, resourceType));
+    }
+    bool isSafeToSendToAnotherThread() const;
+
+    CachedResourceRequest resourceRequest(Document*);
+
+    const String& charset() const { return m_charset; }
+    void setCharset(const String& charset) { m_charset = charset; }
+    void setCrossOriginModeAllowsCookies(bool allowsCookies) { m_crossOriginModeAllowsCookies = allowsCookies; }
+    CachedResource::Type resourceType() const { return m_resourceType; }
+
+private:
+    PreloadRequest(const String& initiator, const String& resourceURL, const KURL& baseURL, CachedResource::Type resourceType)
+        : m_initiator(initiator)
+        , m_resourceURL(resourceURL)
+        , m_baseURL(baseURL)
+        , m_resourceType(resourceType)
+        , m_crossOriginModeAllowsCookies(false)
+    { }
+
+    KURL completeURL(Document*);
+
+    String m_initiator;
+    String m_resourceURL;
+    KURL m_baseURL;
+    String m_charset;
+    CachedResource::Type m_resourceType;
+    bool m_crossOriginModeAllowsCookies;
+};
+
+class HTMLResourcePreloader {
+    WTF_MAKE_NONCOPYABLE(HTMLResourcePreloader); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit HTMLResourcePreloader(Document* document)
+        : m_document(document)
+        , m_weakFactory(this)
+    { }
+
+    void preload(PassOwnPtr<PreloadRequest>);
+
+    WeakPtr<HTMLResourcePreloader> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
+
+private:
+    Document* m_document;
+    WeakPtrFactory<HTMLResourcePreloader> m_weakFactory;
+};
+
+}
+
+#endif
index 3759b28..55c24ce 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef CachedResourceRequest_h
 #define CachedResourceRequest_h
 
+#include "Element.h"
 #include "ResourceLoadPriority.h"
 #include "ResourceLoaderOptions.h"
 #include "ResourceRequest.h"
@@ -34,7 +35,6 @@
 
 namespace WebCore {
 class Document;
-class Element;
 
 class CachedResourceRequest {
 public: