From e19b8f27e16c062c247da5dd29702c3bcffc1704 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 26 Jul 2010 14:18:43 +0300 Subject: [PATCH] Bug 534293 - Make speculative loads initiated by the HTML5 parser take into account. r=jst, a=blocking2.0-betaN. --HG-- extra : rebase_source : 71cd318e90c56cf8f718fb4a4572d17f3ba1a9f3 --- parser/html/nsHtml5SpeculativeLoad.cpp | 3 ++ parser/html/nsHtml5SpeculativeLoad.h | 8 ++++++ parser/html/nsHtml5TreeBuilderCppSupplement.h | 8 ++++++ parser/html/nsHtml5TreeOpExecutor.cpp | 28 ++++++++++++++++++- parser/html/nsHtml5TreeOpExecutor.h | 4 +++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/parser/html/nsHtml5SpeculativeLoad.cpp b/parser/html/nsHtml5SpeculativeLoad.cpp index 5dacb2e2753b..733842b58151 100644 --- a/parser/html/nsHtml5SpeculativeLoad.cpp +++ b/parser/html/nsHtml5SpeculativeLoad.cpp @@ -57,6 +57,9 @@ void nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor) { switch (mOpCode) { + case eSpeculativeLoadBase: + aExecutor->SetSpeculationBase(mUrl); + break; case eSpeculativeLoadImage: aExecutor->PreloadImage(mUrl); break; diff --git a/parser/html/nsHtml5SpeculativeLoad.h b/parser/html/nsHtml5SpeculativeLoad.h index 17334f1d4b85..d6c8c0ba87ee 100644 --- a/parser/html/nsHtml5SpeculativeLoad.h +++ b/parser/html/nsHtml5SpeculativeLoad.h @@ -46,6 +46,7 @@ enum eHtml5SpeculativeLoad { #ifdef DEBUG eSpeculativeLoadUninitialized, #endif + eSpeculativeLoadBase, eSpeculativeLoadImage, eSpeculativeLoadScript, eSpeculativeLoadStyle, @@ -57,6 +58,13 @@ class nsHtml5SpeculativeLoad { nsHtml5SpeculativeLoad(); ~nsHtml5SpeculativeLoad(); + inline void InitBase(const nsAString& aUrl) { + NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, + "Trying to reinitialize a speculative load!"); + mOpCode = eSpeculativeLoadBase; + mUrl.Assign(aUrl); + } + inline void InitImage(const nsAString& aUrl) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 9699fb3bdb46..1f4311eb8dae 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -149,6 +149,14 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm if (url) { mSpeculativeLoadQueue.AppendElement()->InitManifest(*url); } + } else if (nsHtml5Atoms::base == aName && + (mode == NS_HTML5TREE_BUILDER_IN_HEAD || + mode == NS_HTML5TREE_BUILDER_AFTER_HEAD)) { + nsString* url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (url) { + mSpeculativeLoadQueue.AppendElement()->InitBase(*url); + } } break; case kNameSpaceID_SVG: diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 02b62e9ddedd..0ef3a076b36f 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -830,7 +830,18 @@ nsHtml5TreeOpExecutor::InitializeDocWriteParserState(nsAHtml5TreeBuilderState* a already_AddRefed nsHtml5TreeOpExecutor::ConvertIfNotPreloadedYet(const nsAString& aURL) { - nsIURI* base = mDocument->GetDocBaseURI(); + // The URL of the document without + nsIURI* documentURI = mDocument->GetDocumentURI(); + // The URL of the document with non-speculative + nsIURI* documentBaseURI = mDocument->GetDocBaseURI(); + + // If the two above are different, use documentBaseURI. If they are the + // same, the document object isn't aware of a , so attempt to use the + // mSpeculationBaseURI or, failing, that, documentURI. + nsIURI* base = (documentURI == documentBaseURI) ? + (mSpeculationBaseURI ? + mSpeculationBaseURI.get() : documentURI) + : documentBaseURI; const nsCString& charset = mDocument->GetDocumentCharacterSet(); nsCOMPtr uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, charset.get(), base); @@ -882,6 +893,21 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL) mDocument->MaybePreLoadImage(uri); } +void +nsHtml5TreeOpExecutor::SetSpeculationBase(const nsAString& aURL) +{ + if (mSpeculationBaseURI) { + // the first one wins + return; + } + const nsCString& charset = mDocument->GetDocumentCharacterSet(); + nsresult rv = NS_NewURI(getter_AddRefs(mSpeculationBaseURI), aURL, + charset.get(), mDocument->GetDocumentURI()); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to create a URI"); + } +} + #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH PRUint32 nsHtml5TreeOpExecutor::sAppendBatchMaxSize = 0; PRUint32 nsHtml5TreeOpExecutor::sAppendBatchSlotsExamined = 0; diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index 5a44f4f41890..02814e32d2ac 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -109,6 +109,8 @@ class nsHtml5TreeOpExecutor : public nsContentSink, */ nsCStringHashSet mPreloadedURLs; + nsCOMPtr mSpeculationBaseURI; + /** * Whether the parser has started */ @@ -395,6 +397,8 @@ class nsHtml5TreeOpExecutor : public nsContentSink, void PreloadImage(const nsAString& aURL); + void SetSpeculationBase(const nsAString& aURL); + private: nsHtml5Tokenizer* GetTokenizer();