Bug 457810 - Speculatively load stylesheets from preloading. r=mrbkap, sr=bzbarsky

This commit is contained in:
Boris Zbarsky 2009-04-03 10:15:56 -04:00
Родитель a5d4ae3d6c
Коммит 814eb91d33
1 изменённых файлов: 68 добавлений и 62 удалений

Просмотреть файл

@ -71,6 +71,9 @@
#include "nsDataHashtable.h"
#include "nsIThreadPool.h"
#include "nsXPCOMCIDInternal.h"
#include "nsICSSStyleSheet.h"
#include "nsICSSLoaderObserver.h"
#include "nsICSSLoader.h"
#ifdef MOZ_VIEW_SOURCE
#include "nsViewSourceHTML.h"
@ -221,7 +224,7 @@ public:
nsresult StartParsing(nsParser *aParser);
void StopParsing(PRBool aFromDocWrite);
enum PrefetchType { SCRIPT, STYLESHEET, IMAGE };
enum PrefetchType { NONE, SCRIPT, STYLESHEET, IMAGE };
struct PrefetchEntry {
PrefetchType type;
nsString uri;
@ -291,6 +294,21 @@ private:
PRBool mTerminated;
};
/**
* Used if we need to pass an nsICSSLoaderObserver as parameter,
* but don't really need its services
*/
class nsDummyCSSLoaderObserver : public nsICSSLoaderObserver {
public:
NS_IMETHOD
StyleSheetLoaded(nsICSSStyleSheet* aSheet, PRBool aWasAlternate, nsresult aStatus) {
return NS_OK;
}
NS_DECL_ISUPPORTS
};
NS_IMPL_ISUPPORTS1(nsDummyCSSLoaderObserver, nsICSSLoaderObserver)
class nsPreloadURIs : public nsIRunnable {
public:
nsPreloadURIs(nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
@ -343,10 +361,6 @@ nsPreloadURIs::PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::Prefetc
aScriptThread->GetPreloadedURIs();
for (PRUint32 i = 0, e = aURIs.Length(); i < e; ++i) {
const nsSpeculativeScriptThread::PrefetchEntry &pe = aURIs[i];
if (pe.type != nsSpeculativeScriptThread::SCRIPT) {
continue;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), pe.uri, charset.get(), base);
if (NS_FAILED(rv)) {
@ -364,7 +378,15 @@ nsPreloadURIs::PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::Prefetc
alreadyPreloaded.Put(spec, PR_TRUE);
switch (pe.type) {
case nsSpeculativeScriptThread::SCRIPT:
doc->ScriptLoader()->PreloadURI(uri, pe.charset, pe.elementType);
break;
case nsSpeculativeScriptThread::STYLESHEET:
nsCOMPtr<nsICSSLoaderObserver> obs = new nsDummyCSSLoaderObserver();
doc->CSSLoader()->LoadSheet(uri, doc->NodePrincipal(), obs);
break;
}
}
}
@ -553,84 +575,68 @@ nsSpeculativeScriptThread::ProcessToken(CToken *aToken)
nsAutoString src;
nsAutoString elementType;
nsAutoString charset;
PrefetchType ptype = SCRIPT;
nsAutoString href;
nsAutoString rel;
PrefetchType ptype = NONE;
switch (tag) {
#if 0 // TODO Support stylesheet and image preloading.
case eHTMLTag_link: {
// If this is a <link rel=stylesheet> find the src.
PRBool isRelStylesheet = PR_FALSE;
for (; i < attrs; ++i) {
CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
if (attr->GetKey().EqualsLiteral("rel")) {
if (!attr->GetValue().EqualsLiteral("stylesheet")) {
IF_FREE(attr, &mTokenAllocator);
break;
}
isRelStylesheet = PR_TRUE;
} else if (attr->GetKey().EqualsLiteral("src")) {
src.Assign(attr->GetValue());
if (isRelStylesheet) {
IF_FREE(attr, &mTokenAllocator);
break;
}
}
IF_FREE(attr, &mTokenAllocator);
}
if (isRelStylesheet && !src.IsEmpty()) {
AddToPrefetchList(src, STYLESHEET);
}
break;
}
case eHTMLTag_style:
case eHTMLTag_link:
ptype = STYLESHEET;
/* FALL THROUGH */
case eHTMLTag_img:
if (tag == eHTMLTag_img)
ptype = IMAGE;
/* FALL THROUGH */
#endif
break;
case eHTMLTag_script:
if (tag == eHTMLTag_script)
ptype = SCRIPT;
for (; i < attrs; ++i) {
CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
if (attr->GetKey().EqualsLiteral("src")) {
src.Assign(attr->GetValue());
} else if (attr->GetKey().EqualsLiteral("charset")) {
charset.Assign(attr->GetValue());
} else if (attr->GetKey().EqualsLiteral("type")) {
elementType.Assign(attr->GetValue());
}
IF_FREE(attr, &mTokenAllocator);
}
if (!src.IsEmpty()) {
AddToPrefetchList(src, charset, elementType, ptype);
}
break;
default:
break;
}
for (; i < attrs; ++i) {
CToken *attr = mTokenizer->PopToken();
if (!attr) {
break;
}
// We currently handle the following element/attribute combos :
// <link rel="stylesheet" href= charset= type>
// <script src= charset= type=>
if (ptype != NONE) {
// loop over all attributes to extract relevant info
for (; i < attrs ; ++i) {
CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
if (attr->GetKey().EqualsLiteral("src")) {
src.Assign(attr->GetValue());
} else if (attr->GetKey().EqualsLiteral("href")) {
href.Assign(attr->GetValue());
} else if (attr->GetKey().EqualsLiteral("rel")) {
rel.Assign(attr->GetValue());
} else if (attr->GetKey().EqualsLiteral("charset")) {
charset.Assign(attr->GetValue());
} else if (attr->GetKey().EqualsLiteral("type")) {
elementType.Assign(attr->GetValue());
}
IF_FREE(attr, &mTokenAllocator);
}
// ensure we have the right kind if it's a link-element
if (ptype == STYLESHEET) {
if (rel.EqualsLiteral("stylesheet")) {
src = href; // src is the important variable below
} else {
src.Truncate(); // clear src if wrong kind of link
}
}
// add to list if we have a valid src
if (!src.IsEmpty()) {
AddToPrefetchList(src, charset, elementType, ptype);
}
} else {
// Irrelevant tag, but pop and free all its attributes in any case
for (; i < attrs ; ++i) {
CToken *attr = mTokenizer->PopToken();
IF_FREE(attr, &mTokenAllocator);
}
}
break;
}