Files
palemoon27/layout/style/nsLayoutStylesheetCache.cpp
T
roytam1 37477b2115 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1161049 patch 2 - Add comments reflecting what CanPerformOnCompositorThread doesn't check. r=birtles (09854c55c)
- Bug 1161049 patch 3 - Don't send animations to a layer if we're not using off-main-thread compositing. r=mstange (927242bde)
- Bug 1148418 - Make nsDisplayBackgroundColor::Paint use a higher precision floating point type to avoid scrolling artifacts. r=mattwoodrow (3641d43be)
- Bug 1148418 - Follow-up to avoid unused variable warning. r=bustage CLOSED TREE (83d4dd8fe)
- Bug 804975 - Part 2: Add a RuleNodeCacheConditions class and use it instead of a boolean canStoreInRuleTree during style computation. r=dbaron (fce3718c4)
- Bug 804975 - Part 3: Support conditional cached reset structs on rule nodes. r=dbaron (a2a049f56)
- Bug 804975 - Part 4: Cache reset structs on rule nodes for different font-size or writing mode values. r=dbaron (9bac1c6db)
- Bug 77999 - Unified build fix followup. (a2c95b3b4)
- Bug 1169440 patch 1 - Add bitwise operators to nsChangeHint. r=heycam (d30d0a0a2)
- Bug 1169440 patch 2 - Rename style struct MaxDifferenceNeverInherited to DifferenceAlwaysHandledForDescendants. r=heycam (7d1e2cdae)
- Bug 1156988 - Update RestyleManager::{Change,Restyle}HintToString for recent changes. r=dbaron (547e61dd6)
- Bug 1169440 patch 3 - Add nsChangeHint_ReflowChangesSizeOrPosition. r=heycam (0076ee033)
- Bug 1177076 patch 1 - Add logical values for the caption-side property (though not yet handled by layout code). r=heycam (4e8bd065d)
- Bug 1131000. Implement nsMathMLSelectedFrame::ComputeSize to delegate size computation to the selected frame. r=mats (49581cdd7)
- Bug 1172774: for a box with a writing mode orthogonal to its containing block, calculate positioning values (margin, padding and offsets) in the writing mode of the containing block, r=jfkthame (505cd7afb)
- Bug 1177076 patch 2 - Convert nsTableOuterFrame to work with logical coordinates. r=dholbert (300c5cfae)
- Bug 1151993 - Reftest for inline-sizing of orthogonal block frames. r=smontagu (c17e188b1)
- Bug 1144501 - Reftest for sizing of orthogonal frame after block-end margin. r=smontagu (d27d90068)
- Bug 1156021 - Reftest for text-indent specified as percent in vertical writing mode. r=dbaron (d25854ee0)
- Bug 1158549 - Reftest for size constraints in vertical writing mode. r=smontagu (b1d7f74aa)
- Bug 1157752 - Reftest for vertical mode with upright orientation overriding bidi directionality. r=smontagu (b7aedaf06)
- Bug 1152941 - Reftest for orthogonal block with potentially overflowing content. r=dbaron (0fe1d83f4)
- Bug 1077521 - Initial testcases for vertical writing-mode tables. r=smontagu (dbacaf74c)
- Bug 1077521 - Reftest for rowspan in vertical table. r=smontagu (e4b6134bf)
- Bug 1077521 - Reftest for colspan in vertical table. r=smontagu (ece444c32)
- Bug 1177606 - Reftests for vertical tables with specified width. (d7f9ddc3a)
- Bug 1157569 - Reftests for vertical-mode table with border-collapse. r=dholbert (0b9b7eeae)
- Tests for bug 1173958. r=jfkthame (64278818c)
- Bug 1139306: Add a small amount of fuzz to a test on Android, r=tn (b879499c6)
- Bug 1140160 - Handle insertions into a <fieldset> child with display:contents correctly. r=roc (39a24c684)
- partial 1138442 (3d04520fd)
- Bug 1153757 - Tweak DoGetParentStyleContext to exclude pseudos with a non-primary frame from using a display:contents parent as the style context parent. r=heycam (caa35c9ac)
- part of 1144080 (465618308)
- reapply 932958 (f098ad575)
- part of 1153574 (8e4532dc5)
- Bug 1169331 - Always clip rotated buffer quadrant drawing to the fill rect. r=jrmuizel (4693f9c1c)
- Bug 1174332 - Correctly compute box-shadow bounds on themed frames with overflow. r=roc (489b069a5)
- Bug 1169525 - Add the on-demand SVG style sheets when a foreignObjectis encountered within a single style update. r=jwatt (ebe0eb228)
- Bug 1169514 - Part 1: Move noscript rule from the preference style sheet to a cached UA style sheet. r=jwatt (a04979f0f)
- Bug 1169514 - Part 2: Move noframes rules from the preferences style sheet to a cached UA style sheet. r=jwatt (26aae1a45)
- Bug 1174450 part 1 - Split IntrinsicForContainer in two parts; move the latter part to a new function, AddIntrinsicSizeOffset, which applies the padding/border/margin from the given IntrinsicISizeOffsetData. r=jfkthame (37202f0f3)
- Bug 1174450 part 2 - Rename most AddIntrinsicSizeOffset params to follow the aName standard. r=jfkthame (4525fa9c5)
- Bug 1174450 part 3 - Rename AddIntrinsicSizeOffset local vars from xISize to xSize since the code is generic and handles both ISizes and BSizes. r=jfkthame (6a4816b18)
- Bug 1174450 part 4 - Rename the remaining AddIntrinsicSizeOffset params to follow the aName standard. Also rename local var 'w' to 'size' since it may be either a width or height. r=jfkthame (e1132b475)
- Bug 1174450 part 5 - Remove the duplicated min/max calculation in AddIntrinsicSizeOffset, pass a pointer to the calculated absolute values, if any, from IntrinsicForContainer instead. r=jfkthame (85f937449)
- Bug 1174450 part 6 - Add a doc comment for AddIntrinsicSizeOffset and some minor code style fixes. r=jfkthame (1e501c748)
- Bug 1174450 part 7 - Move most of IntrinsicForContainer into a new method, IntrinsicForWM, that takes the writing-mode to use as a parameter. r=jfkthame (db3ba1bc4)
- Bug 1174450 part 8 - Add a new method nsIFrame::IntrinsicBSizeOffsets. r=jfkthame (ef1715d4e)
- Bug 1174450 part 9 - Remove the nsRenderingContext* param from Intrinsic*SizeOffsets methods since it's unused. r=jfkthame (e0fd79cc6)
- Bug 1174450 part 10 - Use the right IntrinsicISizeOffsetData for the given writing-mode (this is what fixes the error reported in this bug). r=jfkthame (efc490611)
- Bug 1174450 part 9b - Make AddIntrinsicSizeOffset take a PhysicalAxis instead of a WritingMode. r=jfkthame (cab48ffef)
- Bug 1174450 part 10b - Rename IntrinsicForWM to IntrinsicForAxis and make it take a PhysicalAxis instead of a WritingMode. r=jfkthame (cd33baeff)
- Bug 1147834: tests for overconstrained relative positioning, r=jfkthame (c2c67b2fc)
- Bug 1157758 - Reftest for Arabic text in vertical-upright mode. r=jdaggett (689b0a84d)
- Bug 1163238 - Reftest for auto margins on orthogonal flow. (c9f5a50ec)
- Bug 1079151 - Tests for position:absolute in vertical writing modes; currently failing 72 out of 96 testcases. r=jfkthame (228756de5)
- Tests for bug 1172774, r=jfkthame (91ff7737d)
- Bug 1174450 part 11 - Tests. (89963b6a7)
- convert file to UTF-8 (f8e2e497a)
2021-02-03 10:56:59 +08:00

468 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsLayoutStylesheetCache.h"
#include "nsAppDirectoryServiceDefs.h"
#include "mozilla/CSSStyleSheet.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Preferences.h"
#include "mozilla/css/Loader.h"
#include "nsIFile.h"
#include "nsNetUtil.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "nsIXULRuntime.h"
#include "nsPrintfCString.h"
using namespace mozilla;
static bool sNumberControlEnabled;
#define NUMBER_CONTROL_PREF "dom.forms.number"
NS_IMPL_ISUPPORTS(
nsLayoutStylesheetCache, nsIObserver, nsIMemoryReporter)
nsresult
nsLayoutStylesheetCache::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, "profile-before-change")) {
mUserContentSheet = nullptr;
mUserChromeSheet = nullptr;
}
else if (!strcmp(aTopic, "profile-do-change")) {
InitFromProfile();
}
else if (strcmp(aTopic, "chrome-flush-skin-caches") == 0 ||
strcmp(aTopic, "chrome-flush-caches") == 0) {
mScrollbarsSheet = nullptr;
mFormsSheet = nullptr;
mNumberControlSheet = nullptr;
}
else {
NS_NOTREACHED("Unexpected observer topic.");
}
return NS_OK;
}
CSSStyleSheet*
nsLayoutStylesheetCache::ScrollbarsSheet()
{
EnsureGlobal();
if (!gStyleCache->mScrollbarsSheet) {
// Scrollbars don't need access to unsafe rules
LoadSheetURL("chrome://global/skin/scrollbars.css",
gStyleCache->mScrollbarsSheet, false);
}
return gStyleCache->mScrollbarsSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::FormsSheet()
{
EnsureGlobal();
if (!gStyleCache->mFormsSheet) {
// forms.css needs access to unsafe rules
LoadSheetURL("resource://gre-resources/forms.css",
gStyleCache->mFormsSheet, true);
}
return gStyleCache->mFormsSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::NumberControlSheet()
{
EnsureGlobal();
if (!sNumberControlEnabled) {
return nullptr;
}
if (!gStyleCache->mNumberControlSheet) {
LoadSheetURL("resource://gre-resources/number-control.css",
gStyleCache->mNumberControlSheet, true);
}
return gStyleCache->mNumberControlSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::UserContentSheet()
{
EnsureGlobal();
return gStyleCache->mUserContentSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::UserChromeSheet()
{
EnsureGlobal();
return gStyleCache->mUserChromeSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::UASheet()
{
EnsureGlobal();
if (!gStyleCache->mUASheet) {
LoadSheetURL("resource://gre-resources/ua.css",
gStyleCache->mUASheet, true);
}
return gStyleCache->mUASheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::HTMLSheet()
{
EnsureGlobal();
if (!gStyleCache->mHTMLSheet) {
LoadSheetURL("resource://gre-resources/html.css",
gStyleCache->mHTMLSheet, true);
}
return gStyleCache->mHTMLSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::MinimalXULSheet()
{
EnsureGlobal();
return gStyleCache->mMinimalXULSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::XULSheet()
{
EnsureGlobal();
return gStyleCache->mXULSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::QuirkSheet()
{
EnsureGlobal();
return gStyleCache->mQuirkSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::FullScreenOverrideSheet()
{
EnsureGlobal();
return gStyleCache->mFullScreenOverrideSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::SVGSheet()
{
EnsureGlobal();
return gStyleCache->mSVGSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::MathMLSheet()
{
EnsureGlobal();
if (!gStyleCache->mMathMLSheet) {
LoadSheetURL("resource://gre-resources/mathml.css",
gStyleCache->mMathMLSheet, true);
}
return gStyleCache->mMathMLSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::CounterStylesSheet()
{
EnsureGlobal();
return gStyleCache->mCounterStylesSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::NoScriptSheet()
{
EnsureGlobal();
if (!gStyleCache->mNoScriptSheet) {
LoadSheetURL("resource://gre-resources/noscript.css",
gStyleCache->mNoScriptSheet, true);
}
return gStyleCache->mNoScriptSheet;
}
CSSStyleSheet*
nsLayoutStylesheetCache::NoFramesSheet()
{
EnsureGlobal();
if (!gStyleCache->mNoFramesSheet) {
LoadSheetURL("resource://gre-resources/noframes.css",
gStyleCache->mNoFramesSheet, true);
}
return gStyleCache->mNoFramesSheet;
}
void
nsLayoutStylesheetCache::Shutdown()
{
NS_IF_RELEASE(gCSSLoader);
gStyleCache = nullptr;
}
MOZ_DEFINE_MALLOC_SIZE_OF(LayoutStylesheetCacheMallocSizeOf)
NS_IMETHODIMP
nsLayoutStylesheetCache::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
return MOZ_COLLECT_REPORT(
"explicit/layout/style-sheet-cache", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(LayoutStylesheetCacheMallocSizeOf),
"Memory used for some built-in style sheets.");
}
size_t
nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
#define MEASURE(s) n += s ? s->SizeOfIncludingThis(aMallocSizeOf) : 0;
MEASURE(mCounterStylesSheet);
MEASURE(mFormsSheet);
MEASURE(mFullScreenOverrideSheet);
MEASURE(mHTMLSheet);
MEASURE(mMathMLSheet);
MEASURE(mMinimalXULSheet);
MEASURE(mNoFramesSheet);
MEASURE(mNoScriptSheet);
MEASURE(mNumberControlSheet);
MEASURE(mQuirkSheet);
MEASURE(mSVGSheet);
MEASURE(mScrollbarsSheet);
MEASURE(mUASheet);
MEASURE(mUserChromeSheet);
MEASURE(mUserContentSheet);
MEASURE(mXULSheet);
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - gCSSLoader
return n;
}
nsLayoutStylesheetCache::nsLayoutStylesheetCache()
{
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
NS_ASSERTION(obsSvc, "No global observer service?");
if (obsSvc) {
obsSvc->AddObserver(this, "profile-before-change", false);
obsSvc->AddObserver(this, "profile-do-change", false);
obsSvc->AddObserver(this, "chrome-flush-skin-caches", false);
obsSvc->AddObserver(this, "chrome-flush-caches", false);
}
InitFromProfile();
// And make sure that we load our UA sheets. No need to do this
// per-profile, since they're profile-invariant.
LoadSheetURL("resource://gre-resources/counterstyles.css",
mCounterStylesSheet, true);
LoadSheetURL("resource://gre-resources/full-screen-override.css",
mFullScreenOverrideSheet, true);
LoadSheetURL("chrome://global/content/minimal-xul.css",
mMinimalXULSheet, true);
LoadSheetURL("resource://gre-resources/quirk.css",
mQuirkSheet, true);
LoadSheetURL("resource://gre/res/svg.css",
mSVGSheet, true);
LoadSheetURL("chrome://global/content/xul.css",
mXULSheet, true);
// The remaining sheets are created on-demand do to their use being rarer
// (which helps save memory for Firefox OS apps) or because they need to
// be re-loadable in DependentPrefChanged.
}
nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
{
mozilla::UnregisterWeakMemoryReporter(this);
MOZ_ASSERT(!gStyleCache);
}
void
nsLayoutStylesheetCache::InitMemoryReporter()
{
mozilla::RegisterWeakMemoryReporter(this);
}
void
nsLayoutStylesheetCache::EnsureGlobal()
{
MOZ_ASSERT(NS_IsMainThread());
if (gStyleCache) return;
gStyleCache = new nsLayoutStylesheetCache();
gStyleCache->InitMemoryReporter();
Preferences::AddBoolVarCache(&sNumberControlEnabled, NUMBER_CONTROL_PREF,
true);
// For each pref that controls a CSS feature that a UA style sheet depends
// on (such as a pref that enables a property that a UA style sheet uses),
// register DependentPrefChanged as a callback to ensure that the relevant
// style sheets will be re-parsed.
Preferences::RegisterCallback(&DependentPrefChanged,
"layout.css.ruby.enabled");
}
void
nsLayoutStylesheetCache::InitFromProfile()
{
nsCOMPtr<nsIXULRuntime> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
if (appInfo) {
bool inSafeMode = false;
appInfo->GetInSafeMode(&inSafeMode);
if (inSafeMode)
return;
}
nsCOMPtr<nsIFile> contentFile;
nsCOMPtr<nsIFile> chromeFile;
NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
getter_AddRefs(contentFile));
if (!contentFile) {
// if we don't have a profile yet, that's OK!
return;
}
contentFile->Clone(getter_AddRefs(chromeFile));
if (!chromeFile) return;
contentFile->Append(NS_LITERAL_STRING("userContent.css"));
chromeFile->Append(NS_LITERAL_STRING("userChrome.css"));
LoadSheetFile(contentFile, mUserContentSheet);
LoadSheetFile(chromeFile, mUserChromeSheet);
}
/* static */ void
nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,
nsRefPtr<CSSStyleSheet>& aSheet,
bool aEnableUnsafeRules)
{
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), aURL);
LoadSheet(uri, aSheet, aEnableUnsafeRules);
if (!aSheet) {
NS_ERROR(nsPrintfCString("Could not load %s", aURL).get());
}
}
void
nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile, nsRefPtr<CSSStyleSheet>& aSheet)
{
bool exists = false;
aFile->Exists(&exists);
if (!exists) return;
nsCOMPtr<nsIURI> uri;
NS_NewFileURI(getter_AddRefs(uri), aFile);
LoadSheet(uri, aSheet, false);
}
static void
ErrorLoadingBuiltinSheet(nsIURI* aURI, const char* aMsg)
{
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);
}
NS_RUNTIMEABORT(nsPrintfCString("%s loading built-in stylesheet '%s'",
aMsg, spec.get()).get());
}
void
nsLayoutStylesheetCache::LoadSheet(nsIURI* aURI,
nsRefPtr<CSSStyleSheet>& aSheet,
bool aEnableUnsafeRules)
{
if (!aURI) {
ErrorLoadingBuiltinSheet(aURI, "null URI");
return;
}
if (!gCSSLoader) {
gCSSLoader = new mozilla::css::Loader();
NS_IF_ADDREF(gCSSLoader);
if (!gCSSLoader) {
ErrorLoadingBuiltinSheet(aURI, "no Loader");
return;
}
}
nsresult rv = gCSSLoader->LoadSheetSync(aURI, aEnableUnsafeRules, true,
getter_AddRefs(aSheet));
if (NS_FAILED(rv)) {
ErrorLoadingBuiltinSheet(aURI,
nsPrintfCString("LoadSheetSync failed with error %x", rv).get());
}
}
/* static */ void
nsLayoutStylesheetCache::InvalidateSheet(nsRefPtr<CSSStyleSheet>& aSheet)
{
MOZ_ASSERT(gCSSLoader, "pref changed before we loaded a sheet?");
if (aSheet) {
gCSSLoader->ObsoleteSheet(aSheet->GetSheetURI());
aSheet = nullptr;
}
}
/* static */ void
nsLayoutStylesheetCache::DependentPrefChanged(const char* aPref, void* aData)
{
MOZ_ASSERT(gStyleCache, "pref changed after shutdown?");
// Cause any UA style sheets whose parsing depends on the value of prefs
// to be re-parsed by dropping the sheet from gCSSLoader's cache then
// setting our cached sheet pointer to null. This will only work for sheets
// that are loaded lazily.
// for layout.css.ruby.enabled
InvalidateSheet(gStyleCache->mUASheet);
InvalidateSheet(gStyleCache->mHTMLSheet);
}
mozilla::StaticRefPtr<nsLayoutStylesheetCache>
nsLayoutStylesheetCache::gStyleCache;
mozilla::css::Loader*
nsLayoutStylesheetCache::gCSSLoader = nullptr;