Bug 1363640 Part 6 - Use bound document's style backend when creating an XBL document. r=heycam
authorTing-Yu Lin <tlin@mozilla.com>
Thu, 11 May 2017 17:16:27 -0700
changeset 360477 7f72289a5cabb3323f1ab4cdbef0306ef6c81ffd
parent 360476 99a6bbeaabef6867077a965acbbfc3c594d23ff3
child 360478 977525db7dbb6d557b87e72230591c1d58e5ed54
push id31883
push userryanvm@gmail.com
push dateThu, 25 May 2017 00:43:48 +0000
treeherdermozilla-central@d10f5ccd882b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1363640
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1363640 Part 6 - Use bound document's style backend when creating an XBL document. r=heycam 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,