Bug 1363640 Part 6 - Use bound document's style backend when creating an XBL document.
The <content> in an XBL document could be injected into documents with
different style backend types. Therefore, we need to set the XBL document's
style backend to the same as the bound document's so that the style
attribute of the content can be processed by the correct backend. <marquee>
elements in xbl-marquee.xml is one such example.
MozReview-Commit-ID: 7M33zlbZqNF
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1252,16 +1252,33 @@ public:
mozilla::StyleBackendType GetStyleBackendType() const {
if (mStyleBackendType == mozilla::StyleBackendType::None) {
const_cast<nsIDocument*>(this)->UpdateStyleBackendType();
}
MOZ_ASSERT(mStyleBackendType != mozilla::StyleBackendType::None);
return mStyleBackendType;
}
+ /**
+ * Documents generally decide their style backend type themselves, and
+ * this is only used for XBL documents to set their style backend type to
+ * their bounding document's.
+ */
+ void SetStyleBackendType(mozilla::StyleBackendType aStyleBackendType) {
+ // We cannot assert mStyleBackendType == mozilla::StyleBackendType::None
+ // because NS_NewXBLDocument() might result GetStyleBackendType() being
+ // called.
+ MOZ_ASSERT(aStyleBackendType != mozilla::StyleBackendType::None,
+ "The StyleBackendType should be set to either Gecko or Servo!");
+ mStyleBackendType = aStyleBackendType;
+ }
+
+ /**
+ * Decide this document's own style backend type.
+ */
void UpdateStyleBackendType();
bool IsStyledByServo() const {
return GetStyleBackendType() == mozilla::StyleBackendType::Servo;
}
/**
* Get this document's StyleImageLoader. This is guaranteed to not return null.
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -179,17 +179,18 @@ nsXBLDocumentInfo::RemovePrototypeBindin
// We do not want to destroy the binding, so just forget it.
bindingToRemove.forget();
}
}
// static
nsresult
-nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo)
+nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo,
+ nsIDocument* aBoundDocument)
{
*aDocInfo = nullptr;
nsAutoCString spec(kXBLCachePrefix);
nsresult rv = PathifyURI(aURI, spec);
NS_ENSURE_SUCCESS(rv, rv);
StartupCache* startupCache = StartupCache::GetSingleton();
@@ -226,16 +227,22 @@ nsXBLDocumentInfo::ReadPrototypeBindings
GetSystemPrincipal(getter_AddRefs(principal));
nsCOMPtr<nsIDOMDocument> domdoc;
rv = NS_NewXBLDocument(getter_AddRefs(domdoc), aURI, nullptr, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
NS_ASSERTION(doc, "Must have a document!");
+
+ // Set the style backend type immediately after creating the XBL document.
+ // Assume gecko if there's no bound document.
+ doc->SetStyleBackendType(aBoundDocument ? aBoundDocument->GetStyleBackendType()
+ : StyleBackendType::Gecko);
+
RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(doc);
while (1) {
uint8_t flags;
nsresult rv = stream->Read8(&flags);
NS_ENSURE_SUCCESS(rv, rv);
if (flags == XBLBinding_Serialize_NoMoreBindings)
break;
--- a/dom/xbl/nsXBLDocumentInfo.h
+++ b/dom/xbl/nsXBLDocumentInfo.h
@@ -41,17 +41,18 @@ public:
void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding);
void FlushSkinStylesheets();
bool IsChrome() { return mIsChrome; }
void MarkInCCGeneration(uint32_t aGeneration);
- static nsresult ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo);
+ static nsresult ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo,
+ nsIDocument* aBoundDocument);
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocumentInfo)
private:
virtual ~nsXBLDocumentInfo();
nsCOMPtr<nsIDocument> mDocument;
bool mScriptAccess;
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -175,17 +175,19 @@ nsXBLResourceLoader::StyleSheetLoaded(St
mResources->AppendStyleSheet(aSheet);
if (!mInLoadResourcesFunc)
mPendingSheets--;
if (mPendingSheets == 0) {
// All stylesheets are loaded.
- mResources->GatherRuleProcessor();
+ if (aSheet->IsGecko()) {
+ mResources->GatherRuleProcessor();
+ }
// XXX Check for mPendingScripts when scripts also come online.
if (!mInLoadResourcesFunc)
NotifyBoundElements();
}
return NS_OK;
}
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -963,17 +963,18 @@ nsXBLService::LoadBindingDocumentInfo(ns
info = cache->GetXBLDocumentInfo(documentURI, styleBackend);
}
bool useStartupCache = useXULCache && IsChromeOrResourceURI(documentURI);
if (!info) {
// Next, look in the startup cache
if (!info && useStartupCache) {
- rv = nsXBLDocumentInfo::ReadPrototypeBindings(documentURI, getter_AddRefs(info));
+ rv = nsXBLDocumentInfo::ReadPrototypeBindings(documentURI, getter_AddRefs(info),
+ aBoundDocument);
if (NS_SUCCEEDED(rv)) {
cache->PutXBLDocumentInfo(info);
}
}
}
#endif
if (!info) {
@@ -1055,16 +1056,21 @@ nsXBLService::FetchBindingDocument(nsICo
if (IsChromeOrResourceURI(aDocumentURI))
aForceSyncLoad = true;
// Create document and contentsink and set them up.
nsCOMPtr<nsIDocument> doc;
rv = NS_NewXMLDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
+ // Set the style backend type before loading the XBL document. Assume
+ // gecko if there's no bound document.
+ doc->SetStyleBackendType(aBoundDocument ? aBoundDocument->GetStyleBackendType()
+ : StyleBackendType::Gecko);
+
nsCOMPtr<nsIXMLContentSink> xblSink;
rv = NS_NewXBLContentSink(getter_AddRefs(xblSink), doc, aDocumentURI, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
// Open channel
// Note: There are some cases where aOriginPrincipal and aBoundDocument are purposely
// set to null (to bypass security checks) when calling LoadBindingDocumentInfo() which calls
// FetchBindingDocument(). LoadInfo will end up with no principal or node in those cases,