Bug 1363640 Part 6 - Use bound document's style backend when creating an XBL document. draft
authorTing-Yu Lin <tlin@mozilla.com>
Thu, 11 May 2017 17:16:27 -0700
changeset 583795 a464685419019f015ef2a98d78a0d0bc8afdea3c
parent 583794 c3b4a20c277e91cac33b16c9e3c591af8a9d8a01
child 583796 ab630f73d21f2f91f8b79e339a0a79c4d9f571e2
push id60548
push userbmo:tlin@mozilla.com
push dateWed, 24 May 2017 17:00:28 +0000
bugs1363640
milestone55.0a1
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
dom/base/nsIDocument.h
dom/xbl/nsXBLDocumentInfo.cpp
dom/xbl/nsXBLDocumentInfo.h
dom/xbl/nsXBLResourceLoader.cpp
dom/xbl/nsXBLService.cpp
--- 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,