diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 1289da1bcaa2..af61e3e01d8a 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -101,6 +101,7 @@ #include "nsIContentIterator.h" #include "nsIDOMStyleSheet.h" #include "nsIStyleSheet.h" +#include "nsIStyleSheetService.h" #include "nsContentPermissionHelper.h" #include "nsNetUtil.h" @@ -3893,6 +3894,21 @@ nsDOMWindowUtils::LeaveChaosMode() return NS_OK; } +NS_IMETHODIMP +nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType, + bool* aRetVal) +{ + MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); + + nsIPresShell* presShell = GetPresShell(); + if (!presShell) { + return NS_ERROR_FAILURE; + } + + return presShell->HasRuleProcessorUsedByMultipleStyleSets(aSheetType, + aRetVal); +} + NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList) diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index eaf9f8129e4b..6a5cdb49f742 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -49,7 +49,7 @@ interface nsIJSRAIIHelper; interface nsIContentPermissionRequest; interface nsIObserver; -[scriptable, uuid(336a8683-5626-4512-a3d5-ec280c13e5c2)] +[scriptable, uuid(bbcb87fb-ce2e-4e05-906b-9258687664e2)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1857,6 +1857,15 @@ interface nsIDOMWindowUtils : nsISupports { * Decrease the chaos mode activation level. See enterChaosMode(). */ void leaveChaosMode(); + + /** + * Returns whether the document's style set's rule processor for the + * specified level of the cascade is shared by multiple style sets. + * (Used by tests to ensure that certain optimizations do not regress.) + * + * @param aSheetType One of the nsIStyleSheetService.*_SHEET constants. + */ + bool hasRuleProcessorUsedByMultipleStyleSets(in unsigned long aSheetType); }; [scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)] diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index c15624856c67..5bf93287ca3d 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1568,6 +1568,15 @@ public: // Whether we should assume all images are visible. virtual bool AssumeAllImagesVisible() = 0; + /** + * Returns whether the document's style set's rule processor for the + * specified level of the cascade is shared by multiple style sets. + * + * @param aSheetType One of the nsIStyleSheetService.*_SHEET constants. + */ + nsresult HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType, + bool* aRetVal); + /** * Refresh observer management. */ diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 064891088275..663a498c3d2b 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -10894,3 +10894,27 @@ nsIPresShell::SyncWindowProperties(nsView* aView) nsContainerFrame::SyncWindowProperties(mPresContext, frame, aView, &rcx, 0); } } + +nsresult +nsIPresShell::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType, + bool* aRetVal) +{ + nsStyleSet::sheetType type; + switch (aSheetType) { + case nsIStyleSheetService::AGENT_SHEET: + type = nsStyleSet::eAgentSheet; + break; + case nsIStyleSheetService::USER_SHEET: + type = nsStyleSet::eUserSheet; + break; + case nsIStyleSheetService::AUTHOR_SHEET: + type = nsStyleSet::eDocSheet; + break; + default: + MOZ_ASSERT(false, "unexpected aSheetType value"); + return NS_ERROR_ILLEGAL_VALUE; + } + + *aRetVal = mStyleSet->HasRuleProcessorUsedByMultipleStyleSets(type); + return NS_OK; +} diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index 22015a7425e1..93fa68656dbf 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -183,6 +183,7 @@ public: mInRuleProcessorCache = aVal; } bool IsInRuleProcessorCache() const { return mInRuleProcessorCache; } + bool IsUsedByMultipleStyleSets() const { return mStyleSetRefCnt > 1; } #ifdef XP_WIN // Cached theme identifier for the moz-windows-theme media query. diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 633cc4adccb6..7b8268f7ba96 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -2467,3 +2467,15 @@ nsStyleSet::InitialStyleRule() } return mInitialStyleRule; } + +bool +nsStyleSet::HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType) +{ + MOZ_ASSERT(aSheetType < ArrayLength(mRuleProcessors)); + if (!IsCSSSheetType(aSheetType) || !mRuleProcessors[aSheetType]) { + return false; + } + nsCSSRuleProcessor* rp = + static_cast(mRuleProcessors[aSheetType].get()); + return rp->IsUsedByMultipleStyleSets(); +} diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 40c290d68bdb..717d5d00a71a 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -394,6 +394,8 @@ class nsStyleSet final nsIStyleRule* InitialStyleRule(); + bool HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType); + private: nsStyleSet(const nsStyleSet& aCopy) = delete; nsStyleSet& operator=(const nsStyleSet& aCopy) = delete; diff --git a/layout/style/test/browser.ini b/layout/style/test/browser.ini index 42324bfc250a..0ddea4016fef 100644 --- a/layout/style/test/browser.ini +++ b/layout/style/test/browser.ini @@ -2,6 +2,8 @@ support-files = bug453896_iframe.html media_queries_iframe.html + newtab_share_rule_processors.html [browser_bug453896.js] skip-if = e10s # Bug ?????? - test touches content (TypeError: doc.documentElement is null) +[browser_newtab_share_rule_processors.js] diff --git a/layout/style/test/browser_newtab_share_rule_processors.js b/layout/style/test/browser_newtab_share_rule_processors.js new file mode 100644 index 000000000000..810f5f86e6b3 --- /dev/null +++ b/layout/style/test/browser_newtab_share_rule_processors.js @@ -0,0 +1,38 @@ +var theTab; +var theBrowser; + +function listener(evt) { + if (evt.target == theBrowser.contentDocument) { + doTest(); + } +} + +function test() { + waitForExplicitFinish(); + var testURL = getRootDirectory(gTestPath) + "newtab_share_rule_processors.html"; + theTab = gBrowser.addTab(testURL); + theBrowser = gBrowser.getBrowserForTab(theTab); + theBrowser.addEventListener("load", listener, true); +} + +function doTest() { + theBrowser.removeEventListener("load", listener, true); + var winUtils = theBrowser.contentWindow + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + // The initial set of agent-level sheets should have a rule processor that's + // also being used by another document. + ok(winUtils.hasRuleProcessorUsedByMultipleStyleSets(Ci.nsIStyleSheetService.AGENT_SHEET), + "agent sheet rule processor is used by multiple style sets"); + // Document-level sheets currently never get shared rule processors. + ok(!winUtils.hasRuleProcessorUsedByMultipleStyleSets(Ci.nsIStyleSheetService.AUTHOR_SHEET), + "author sheet rule processor is not used by multiple style sets"); + // Adding a unique style sheet to the agent level will cause it to have a + // rule processor that is unique. + theBrowser.contentWindow.wrappedJSObject.addAgentSheet(); + ok(!winUtils.hasRuleProcessorUsedByMultipleStyleSets(Ci.nsIStyleSheetService.AGENT_SHEET), + "agent sheet rule processor is not used by multiple style sets after " + + "having a unique sheet added to it"); + gBrowser.removeTab(theTab); + finish(); +} diff --git a/layout/style/test/newtab_share_rule_processors.html b/layout/style/test/newtab_share_rule_processors.html new file mode 100644 index 000000000000..bdfed1145b38 --- /dev/null +++ b/layout/style/test/newtab_share_rule_processors.html @@ -0,0 +1,22 @@ + + +

Hello

+