Bug 1253788 - Don't reload inline chrome:// style sheets in nsXBLPrototypeResources. r=bzbarsky
authorCameron McCormack <cam@mcc.id.au>
Sat, 26 Mar 2016 17:02:30 +1100
changeset 290555 a1ff072697463083c31594b7281176c2cd7e16b8
parent 290554 880f8af31133bd65dde834e9472a66189335a79e
child 290556 1bfc39d87c3e71ffde4482abcd976668155c115b
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1253788
milestone48.0a1
Bug 1253788 - Don't reload inline chrome:// style sheets in nsXBLPrototypeResources. r=bzbarsky
chrome/nsChromeRegistry.cpp
dom/base/nsStyleLinkElement.cpp
dom/xbl/nsXBLPrototypeResources.cpp
layout/style/CSSStyleSheet.h
layout/style/StyleSheetHandle.h
layout/style/StyleSheetHandleInlines.h
layout/style/StyleSheetInfo.h
--- a/chrome/nsChromeRegistry.cpp
+++ b/chrome/nsChromeRegistry.cpp
@@ -439,21 +439,23 @@ nsresult nsChromeRegistry::RefreshWindow
   // Iterate over the style sheets.
   for (int32_t i = 0; i < count; i++) {
     // Get the style sheet
     StyleSheetHandle styleSheet = document->GetStyleSheetAt(i);
     oldSheets.AppendElement(styleSheet);
   }
 
   // Iterate over our old sheets and kick off a sync load of the new
-  // sheet if and only if it's a chrome URL.
+  // sheet if and only if it's a non-inline sheet with a chrome URL.
   for (StyleSheetHandle sheet : oldSheets) {
-    nsIURI* uri = sheet ? sheet->GetOriginalURI() : nullptr;
+    MOZ_ASSERT(sheet, "GetStyleSheetAt shouldn't return nullptr for "
+                      "in-range sheet indexes");
+    nsIURI* uri = sheet->GetSheetURI();
 
-    if (uri && IsChromeURI(uri)) {
+    if (!sheet->IsInline() && IsChromeURI(uri)) {
       // Reload the sheet.
       StyleSheetHandle::RefPtr newSheet;
       // XXX what about chrome sheets that have a title or are disabled?  This
       // only works by sheer dumb luck.
       document->LoadChromeSheetSync(uri, false, &newSheet);
       // Even if it's null, we put in in there.
       newSheets.AppendElement(newSheet);
     } else {
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -214,17 +214,17 @@ nsStyleLinkElement::UpdateStyleSheet(nsI
 {
   if (aForceReload) {
     // We remove this stylesheet from the cache to load a new version.
     nsCOMPtr<nsIContent> thisContent;
     CallQueryInterface(this, getter_AddRefs(thisContent));
     nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
       thisContent->OwnerDoc() : thisContent->GetUncomposedDoc();
     if (doc && doc->CSSLoader()->GetEnabled() &&
-        mStyleSheet && mStyleSheet->GetOriginalURI()) {
+        mStyleSheet && !mStyleSheet->IsInline()) {
       doc->CSSLoader()->ObsoleteSheet(mStyleSheet->GetOriginalURI());
     }
   }
   return DoUpdateStyleSheet(nullptr, nullptr, aObserver, aWillNotify,
                             aIsAlternate, aForceReload);
 }
 
 nsresult
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -75,31 +75,33 @@ nsXBLPrototypeResources::FlushSkinSheets
   // If doc is null, we're in the process of tearing things down, so just
   // return without rebuilding anything.
   if (!doc) {
     return NS_OK;
   }
 
   // We have scoped stylesheets.  Reload any chrome stylesheets we
   // encounter.  (If they aren't skin sheets, it doesn't matter, since
-  // they'll still be in the chrome cache.
+  // they'll still be in the chrome cache.  Skip inline sheets, which
+  // skin sheets can't be, and which in any case don't have a usable
+  // URL to reload.)
 
   nsTArray<StyleSheetHandle::RefPtr> oldSheets;
 
   oldSheets.SwapElements(mStyleSheetList);
 
   mozilla::css::Loader* cssLoader = doc->CSSLoader();
 
   for (size_t i = 0, count = oldSheets.Length(); i < count; ++i) {
     StyleSheetHandle oldSheet = oldSheets[i];
 
     nsIURI* uri = oldSheet->GetSheetURI();
 
     StyleSheetHandle::RefPtr newSheet;
-    if (IsChromeURI(uri)) {
+    if (!oldSheet->IsInline() && IsChromeURI(uri)) {
       if (NS_FAILED(cssLoader->LoadSheetSync(uri, &newSheet)))
         continue;
     }
     else {
       newSheet = oldSheet;
     }
 
     mStyleSheetList.AppendElement(newSheet);
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -220,16 +220,19 @@ public:
    */
   nsresult InsertRuleInternal(const nsAString& aRule,
                               uint32_t aIndex, uint32_t* aReturn);
 
   /* Get the URI this sheet was originally loaded from, if any.  Can
      return null */
   nsIURI* GetOriginalURI() const { return mInner->mOriginalSheetURI; }
 
+  // Whether the sheet is for an inline <style> element.
+  bool IsInline() const { return mInner->IsInline(); }
+
   // nsICSSLoaderObserver interface
   NS_IMETHOD StyleSheetLoaded(StyleSheetHandle aSheet, bool aWasAlternate,
                               nsresult aStatus) override;
 
   void EnsureUniqueInner();
 
   // Append all of this sheet's child sheets to aArray.
   void AppendAllChildSheets(nsTArray<CSSStyleSheet*>& aArray);
--- a/layout/style/StyleSheetHandle.h
+++ b/layout/style/StyleSheetHandle.h
@@ -99,16 +99,17 @@ public:
     inline MozExternalRefCountType AddRef();
     inline MozExternalRefCountType Release();
 
     // Style sheet interface.  These inline methods are defined in
     // StyleSheetHandleInlines.h and just forward to the underlying
     // CSSStyleSheet or ServoStyleSheet.  See corresponding comments in
     // CSSStyleSheet.h for descriptions of these methods.
 
+    inline bool IsInline() const;
     inline nsIURI* GetSheetURI() const;
     inline nsIURI* GetOriginalURI() const;
     inline nsIURI* GetBaseURI() const;
     inline void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI, nsIURI* aBaseURI);
     inline bool IsApplicable() const;
     inline void SetParsingMode(css::SheetParsingMode aMode);
     inline bool HasRules() const;
     inline nsIDocument* GetOwningDocument() const;
--- a/layout/style/StyleSheetHandleInlines.h
+++ b/layout/style/StyleSheetHandleInlines.h
@@ -43,16 +43,22 @@ StyleSheetHandle::Ptr::AddRef()
 }
 
 MozExternalRefCountType
 StyleSheetHandle::Ptr::Release()
 {
   FORWARD(Release, ());
 }
 
+bool
+StyleSheetHandle::Ptr::IsInline() const
+{
+  FORWARD(IsInline, ());
+}
+
 nsIURI*
 StyleSheetHandle::Ptr::GetSheetURI() const
 {
   FORWARD(GetSheetURI, ());
 }
 
 nsIURI*
 StyleSheetHandle::Ptr::GetOriginalURI() const
--- a/layout/style/StyleSheetInfo.h
+++ b/layout/style/StyleSheetInfo.h
@@ -35,16 +35,19 @@ public:
                  const dom::SRIMetadata& aIntegrity);
   StyleSheetInfo(const StyleSheetInfo& aCopy);
 
   nsIURI* GetSheetURI() const { return mSheetURI; }
   nsIURI* GetOriginalURI() const { return mOriginalSheetURI; }
   nsIURI* GetBaseURI() const { return mBaseURI; }
   void SetURIs(nsIURI* aSheetURI, nsIURI* aOriginalSheetURI, nsIURI* aBaseURI);
 
+  // Whether the sheet is for an inline <style> element.
+  bool IsInline() const { return !mOriginalSheetURI; }
+
   nsIPrincipal* Principal() const { return mPrincipal; }
   void SetPrincipal(nsIPrincipal* aPrincipal);
 
   CORSMode GetCORSMode() const { return mCORSMode; }
   net::ReferrerPolicy GetReferrerPolicy() const { return mReferrerPolicy; }
   void GetIntegrity(dom::SRIMetadata& aResult) const { aResult = mIntegrity; }
 
 protected: