Bug 1008455 - Avoid loading the xul.css UA style sheet when possible. r=bz CLOSED TREE

--HG--
rename : toolkit/content/xul.css => toolkit/content/minimal-xul.css
This commit is contained in:
Jonathan Watt 2014-05-24 19:51:06 +01:00
parent 745f910b48
commit 74572624da
11 changed files with 325 additions and 123 deletions

View File

@ -70,9 +70,11 @@ public:
* appended to a parent, this will be called after the node has been added to
* the parent's child list and before nsIDocumentObserver notifications for
* the addition are dispatched.
* @param aDocument The new document for the content node. Must match the
* current document of aParent, if aParent is not null.
* May not be null if aParent is null.
* @param aDocument The new document for the content node. May not be null
* if aParent is null. Must match the current document of
* aParent, if aParent is not null (note that
* aParent->GetCurrentDoc() can be null, in which case this
* must also be null).
* @param aParent The new parent for the content node. May be null if the
* node is being bound as a direct child of the document.
* @param aBindingParent The new binding parent for the content node.

View File

@ -1213,14 +1213,32 @@ public:
nsAString& aEncoding,
nsAString& Standalone) = 0;
/**
* Returns true if this is what HTML 5 calls an "HTML document" (for example
* regular HTML document with Content-Type "text/html", image documents and
* media documents). Returns false for XHTML and any other documents parsed
* by the XML parser.
*/
bool IsHTML() const
{
return mIsRegularHTML;
}
bool IsXML() const
{
return !IsHTML();
}
bool IsXUL() const
{
return mIsXUL;
}
bool IsUnstyledDocument()
{
return IsLoadedAsData() || IsLoadedAsInteractiveData();
}
bool LoadsFullXULStyleSheetUpFront()
{
return IsXUL() || AllowXULXBL();
}
virtual bool IsScriptEnabled() = 0;

View File

@ -17,6 +17,11 @@ namespace dom {
class SVGDocument MOZ_FINAL : public XMLDocument
{
public:
SVGDocument()
: XMLDocument("image/svg+xml")
{
}
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
// WebIDL API

View File

@ -33,6 +33,7 @@
#include "nsIDOMElementCSSInlineStyle.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDocument.h"
#include "nsLayoutStylesheetCache.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/EventStates.h"
@ -729,6 +730,68 @@ nsXULElement::UpdateEditableState(bool aNotify)
UpdateState(aNotify);
}
/**
* Returns true if the user-agent style sheet rules for this XUL element are
* in minimal-xul.css instead of xul.css.
*/
static inline bool XULElementsRulesInMinimalXULSheet(nsIAtom* aTag)
{
return // scrollbar parts:
aTag == nsGkAtoms::scrollbar ||
aTag == nsGkAtoms::scrollbarbutton ||
aTag == nsGkAtoms::scrollcorner ||
aTag == nsGkAtoms::slider ||
aTag == nsGkAtoms::thumb ||
aTag == nsGkAtoms::scale ||
// other
aTag == nsGkAtoms::resizer ||
aTag == nsGkAtoms::label ||
aTag == nsGkAtoms::videocontrols;
}
#ifdef DEBUG
/**
* Returns true if aElement is a XUL element created by the video controls
* binding. HTML <video> and <audio> bindings pull in this binding. This
* binding creates lots of different types of XUL elements.
*/
static inline bool
IsInVideoControls(nsXULElement* aElement)
{
nsIContent* ancestor = aElement->GetParent();
while (ancestor) {
if (ancestor->NodeInfo()->Equals(nsGkAtoms::videocontrols, kNameSpaceID_XUL)) {
return true;
}
ancestor = ancestor->GetParent();
}
return false;
}
/**
* Returns true if aElement is an element created by the <binding
* id="feedreaderUI"> binding or one of the bindings bound to such an element.
* element in one of the binding for such an element. Only
* subscribe.xhtml#feedSubscribeLine pulls in the feedreaderUI binding. This
* binding creates lots of different types of XUL elements.
*/
bool
IsInFeedSubscribeLine(nsXULElement* aElement)
{
nsIContent* bindingParent = aElement->GetBindingParent();
if (bindingParent) {
while (bindingParent->GetBindingParent()) {
bindingParent = bindingParent->GetBindingParent();
}
nsIAtom* idAtom = bindingParent->GetID();
if (idAtom && idAtom->Equals(NS_LITERAL_STRING("feedSubscribeLine"))) {
return true;
}
}
return false;
}
#endif
nsresult
nsXULElement::BindToTree(nsIDocument* aDocument,
nsIContent* aParent,
@ -740,6 +803,38 @@ nsXULElement::BindToTree(nsIDocument* aDocument,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument &&
!aDocument->LoadsFullXULStyleSheetUpFront() &&
!aDocument->IsUnstyledDocument()) {
// To save CPU cycles and memory, non-XUL documents only load the user
// agent style sheet rules for a minimal set of XUL elements such as
// 'scrollbar' that may be created implicitly for their content (those
// rules being in minimal-xul.css). This is where we make sure that all
// the other XUL UA style sheet rules (xul.css) have been loaded if the
// minimal set is not sufficient.
//
// We do this during binding, not element construction, because elements
// can be moved from the document that creates them to another document.
if (!XULElementsRulesInMinimalXULSheet(Tag())) {
aDocument->EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::XULSheet());
// To keep memory usage down it is important that we try and avoid
// pulling xul.css into non-XUL documents. That should be very rare, and
// for HTML we currently should only pull it in if the document contains
// an <audio> or <video> element. This assertion is here to make sure
// that we don't fail to notice if a change to bindings causes us to
// start pulling in xul.css much more frequently. If this assertion
// fails then we need to figure out why, and how we can continue to avoid
// pulling in xul.css.
// Note that add-ons may introduce bindings that cause this assertion to
// fire.
NS_ASSERTION(IsInVideoControls(this) ||
IsInFeedSubscribeLine(this),
"Unexpected XUL element in non-XUL doc");
}
}
if (aDocument) {
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Missing a script blocker!");

View File

@ -2280,6 +2280,20 @@ nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument,
// after the html.css and so forth that the UA sheet imports).
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, quirkClone);
styleSet->SetQuirkStyleSheet(quirkClone);
if (aDocument->LoadsFullXULStyleSheetUpFront()) {
// nsXULElement::BindToTree loads xul.css on-demand if we don't load it
// up-front here.
sheet = nsLayoutStylesheetCache::XULSheet();
if (sheet) {
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
}
}
sheet = nsLayoutStylesheetCache::MinimalXULSheet();
if (sheet) {
// Load the minimal XUL rules for scrollbars and a few other XUL things
// that non-XUL (typically HTML) documents commonly use.
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
}
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet,
nsLayoutStylesheetCache::UASheet());

View File

@ -148,6 +148,26 @@ nsLayoutStylesheetCache::UASheet()
return gStyleCache->mUASheet;
}
nsCSSStyleSheet*
nsLayoutStylesheetCache::MinimalXULSheet()
{
EnsureGlobal();
if (!gStyleCache)
return nullptr;
return gStyleCache->mMinimalXULSheet;
}
nsCSSStyleSheet*
nsLayoutStylesheetCache::XULSheet()
{
EnsureGlobal();
if (!gStyleCache)
return nullptr;
return gStyleCache->mXULSheet;
}
nsCSSStyleSheet*
nsLayoutStylesheetCache::QuirkSheet()
{
@ -230,6 +250,8 @@ nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
MEASURE(mUserContentSheet);
MEASURE(mUserChromeSheet);
MEASURE(mUASheet);
MEASURE(mMinimalXULSheet);
MEASURE(mXULSheet);
MEASURE(mQuirkSheet);
MEASURE(mFullScreenOverrideSheet);
MEASURE(mSVGSheet);
@ -268,6 +290,18 @@ nsLayoutStylesheetCache::nsLayoutStylesheetCache()
}
NS_ASSERTION(mUASheet, "Could not load ua.css");
NS_NewURI(getter_AddRefs(uri), "chrome://global/content/minimal-xul.css");
if (uri) {
LoadSheet(uri, mMinimalXULSheet, true);
}
NS_ASSERTION(mMinimalXULSheet, "Could not load minimal-xul.css");
NS_NewURI(getter_AddRefs(uri), "chrome://global/content/xul.css");
if (uri) {
LoadSheet(uri, mXULSheet, true);
}
NS_ASSERTION(mXULSheet, "Could not load xul.css");
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/quirk.css");
if (uri) {
LoadSheet(uri, mQuirkSheet, true);

View File

@ -39,6 +39,8 @@ class nsLayoutStylesheetCache MOZ_FINAL
static nsCSSStyleSheet* UserContentSheet();
static nsCSSStyleSheet* UserChromeSheet();
static nsCSSStyleSheet* UASheet();
static nsCSSStyleSheet* MinimalXULSheet();
static nsCSSStyleSheet* XULSheet();
static nsCSSStyleSheet* QuirkSheet();
static nsCSSStyleSheet* FullScreenOverrideSheet();
static nsCSSStyleSheet* SVGSheet();
@ -67,6 +69,8 @@ private:
nsRefPtr<nsCSSStyleSheet> mUserContentSheet;
nsRefPtr<nsCSSStyleSheet> mUserChromeSheet;
nsRefPtr<nsCSSStyleSheet> mUASheet;
nsRefPtr<nsCSSStyleSheet> mMinimalXULSheet;
nsRefPtr<nsCSSStyleSheet> mXULSheet;
nsRefPtr<nsCSSStyleSheet> mQuirkSheet;
nsRefPtr<nsCSSStyleSheet> mFullScreenOverrideSheet;
nsRefPtr<nsCSSStyleSheet> mSVGSheet;

View File

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@import url(resource://gre-resources/html.css);
@import url(chrome://global/content/xul.css);
@namespace parsererror url(http://www.mozilla.org/newlayout/xml/parsererror.xml);
@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);

View File

@ -7,6 +7,7 @@ toolkit.jar:
% override chrome://global/content/nsTransferable.js chrome://global/content/nsDragAndDrop.js
* content/global/license.html (license.html)
content/global/XPCNativeWrapper.js (XPCNativeWrapper.js)
* content/global/minimal-xul.css (minimal-xul.css)
* content/global/xul.css (xul.css)
content/global/textbox.css (textbox.css)
content/global/menulist.css (menulist.css)

View File

@ -0,0 +1,133 @@
/* 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/. */
/**
* This file should only contain a minimal set of rules for the XUL elements
* that may be implicitly created as part of HTML/SVG documents (e.g.
* scrollbars). Rules for everything else related to XUL can be found in
* xul.css. (This split of the XUL rules is to minimize memory use and improve
* performance in HTML/SVG documents.)
*
* This file should also not contain any app specific styling. Defaults for
* widgets of a particular application should be in that application's style
* sheet. For example style definitions for navigator can be found in
* navigator.css.
*
* THIS FILE IS LOCKED DOWN. YOU ARE NOT ALLOWED TO MODIFY IT WITHOUT FIRST
* HAVING YOUR CHANGES REVIEWED BY enndeakin@gmail.com
*/
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
@namespace html url("http://www.w3.org/1999/xhtml"); /* namespace for HTML elements */
* {
-moz-user-focus: ignore;
-moz-user-select: none;
display: -moz-box;
box-sizing: border-box;
}
:root {
text-rendering: optimizeLegibility;
-moz-binding: url("chrome://global/content/bindings/general.xml#root-element");
-moz-control-character-visibility: visible;
}
:root:-moz-locale-dir(rtl) {
direction: rtl;
}
/* hide the content and destroy the frame */
[hidden="true"] {
display: none;
}
/* hide the content, but don't destroy the frames */
[collapsed="true"],
[moz-collapsed="true"] {
visibility: collapse;
}
/********** label **********/
description {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-base");
}
label {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-label");
}
label.text-link, label[onclick] {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-link");
-moz-user-focus: normal;
}
label[control], label.radio-label, label.checkbox-label, label.toolbarbutton-multiline-text {
-moz-binding: url("chrome://global/content/bindings/text.xml#label-control");
}
html|span.accesskey {
text-decoration: underline;
}
/********** resizer **********/
resizer {
-moz-binding: url("chrome://global/content/bindings/resizer.xml#resizer");
position: relative;
z-index: 2147483647;
}
/********** scrollbar **********/
/* Scrollbars are never flipped even if BiDI kicks in. */
scrollbar[orient="horizontal"] {
direction: ltr;
}
thumb {
-moz-binding: url(chrome://global/content/bindings/scrollbar.xml#thumb);
display: -moz-box !important;
}
.scale-thumb {
-moz-binding: url(chrome://global/content/bindings/scale.xml#scalethumb);
}
scrollbar, scrollbarbutton, scrollcorner, slider, thumb, scale {
-moz-user-select: none;
}
scrollcorner {
display: -moz-box !important;
}
scrollcorner[hidden="true"] {
display: none !important;
}
scrollbar[value="hidden"] {
visibility: hidden;
}
scale {
-moz-binding: url(chrome://global/content/bindings/scale.xml#scale);
}
.scale-slider {
-moz-binding: url(chrome://global/content/bindings/scale.xml#scaleslider);
-moz-user-focus: normal;
}
scrollbarbutton[sbattr="scrollbar-up-top"]:not(:-moz-system-metric(scrollbar-start-backward)),
scrollbarbutton[sbattr="scrollbar-down-top"]:not(:-moz-system-metric(scrollbar-start-forward)),
scrollbarbutton[sbattr="scrollbar-up-bottom"]:not(:-moz-system-metric(scrollbar-end-backward)),
scrollbarbutton[sbattr="scrollbar-down-bottom"]:not(:-moz-system-metric(scrollbar-end-forward)) {
display: none;
}
thumb[sbattr="scrollbar-thumb"]:-moz-system-metric(scrollbar-thumb-proportional) {
-moz-box-flex: 1;
}

View File

@ -2,47 +2,27 @@
* 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/. */
/** this should only contain XUL dialog and document window widget defaults. Defaults for widgets of
a particular application should be in that application's style sheet.
For example style definitions for navigator can be found in navigator.css
THIS FILE IS LOCKED DOWN. YOU ARE NOT ALLOWED TO MODIFY IT WITHOUT FIRST HAVING YOUR
CHANGES REVIEWED BY enndeakin@sympatico.ca
**/
/**
* A minimal set of rules for the XUL elements that may be implicitly created
* as part of HTML/SVG documents (e.g. scrollbars) can be found over in
* minimal-xul.css. Rules for everything else related to XUL can be found in
* this file. Make sure you choose the correct style sheet when adding new
* rules. (This split of the XUL rules is to minimize memory use and improve
* performance in HTML/SVG documents.)
*
* This file should also not contain any app specific styling. Defaults for
* widgets of a particular application should be in that application's style
* sheet. For example, style definitions for navigator can be found in
* navigator.css.
*
* THIS FILE IS LOCKED DOWN. YOU ARE NOT ALLOWED TO MODIFY IT WITHOUT FIRST
* HAVING YOUR CHANGES REVIEWED BY enndeakin@gmail.com
*/
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
@namespace html url("http://www.w3.org/1999/xhtml"); /* namespace for HTML elements */
@namespace xbl url("http://www.mozilla.org/xbl"); /* namespace for XBL elements */
* {
-moz-user-focus: ignore;
-moz-user-select: none;
display: -moz-box;
box-sizing: border-box;
}
:root {
text-rendering: optimizeLegibility;
-moz-binding: url("chrome://global/content/bindings/general.xml#root-element");
-moz-control-character-visibility: visible;
}
:root:-moz-locale-dir(rtl) {
direction: rtl;
}
/* hide the content and destroy the frame */
[hidden="true"] {
display: none;
}
/* hide the content, but don't destroy the frames */
[collapsed="true"],
[moz-collapsed="true"] {
visibility: collapse;
}
/* ::::::::::
:: Rules for 'hiding' portions of the chrome for special
:: kinds of windows (not JUST browser windows) with toolbars
@ -749,29 +729,6 @@ progressmeter {
-moz-box-direction: inherit;
}
/********** label **********/
description {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-base");
}
label {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-label");
}
label.text-link, label[onclick] {
-moz-binding: url("chrome://global/content/bindings/text.xml#text-link");
-moz-user-focus: normal;
}
label[control], label.radio-label, label.checkbox-label, label.toolbarbutton-multiline-text {
-moz-binding: url("chrome://global/content/bindings/text.xml#label-control");
}
html|span.accesskey {
text-decoration: underline;
}
/********** textbox **********/
textbox {
@ -961,14 +918,6 @@ dropmarker {
-moz-binding: url("chrome://global/content/bindings/general.xml#dropmarker");
}
/********** resizer **********/
resizer {
-moz-binding: url("chrome://global/content/bindings/resizer.xml#resizer");
position: relative;
z-index: 2147483647;
}
/********** splitter **********/
splitter {
@ -987,58 +936,6 @@ grippy {
-moz-box-ordinal-group: 2147483646;
}
/********** scrollbar **********/
/* Scrollbars are never flipped even if BiDI kicks in. */
scrollbar[orient="horizontal"] {
direction: ltr;
}
thumb {
-moz-binding: url(chrome://global/content/bindings/scrollbar.xml#thumb);
display: -moz-box !important;
}
.scale-thumb {
-moz-binding: url(chrome://global/content/bindings/scale.xml#scalethumb);
}
scrollbar, scrollbarbutton, scrollcorner, slider, thumb, scale {
-moz-user-select: none;
}
scrollcorner {
display: -moz-box !important;
}
scrollcorner[hidden="true"] {
display: none !important;
}
scrollbar[value="hidden"] {
visibility: hidden;
}
scale {
-moz-binding: url(chrome://global/content/bindings/scale.xml#scale);
}
.scale-slider {
-moz-binding: url(chrome://global/content/bindings/scale.xml#scaleslider);
-moz-user-focus: normal;
}
scrollbarbutton[sbattr="scrollbar-up-top"]:not(:-moz-system-metric(scrollbar-start-backward)),
scrollbarbutton[sbattr="scrollbar-down-top"]:not(:-moz-system-metric(scrollbar-start-forward)),
scrollbarbutton[sbattr="scrollbar-up-bottom"]:not(:-moz-system-metric(scrollbar-end-backward)),
scrollbarbutton[sbattr="scrollbar-down-bottom"]:not(:-moz-system-metric(scrollbar-end-forward)) {
display: none;
}
thumb[sbattr="scrollbar-thumb"]:-moz-system-metric(scrollbar-thumb-proportional) {
-moz-box-flex: 1;
}
/******** scrollbox ********/
scrollbox {