From 7792c4a45ffad9ec77ec363e97dda576f66d3747 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Sat, 24 May 2014 21:37:48 +0100 Subject: [PATCH] Bug 1011806 - Stop loading user-agent and user style sheets for SVG-as-an-image (the main UA sheets svg.css, html.css, etc. will still load on demand). r=bz CLOSED TREE --- content/svg/document/src/SVGDocument.cpp | 62 ++++++++++++++++++++++++ layout/base/nsDocumentViewer.cpp | 17 ++++++- layout/base/nsStyleSheetService.cpp | 3 ++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/content/svg/document/src/SVGDocument.cpp b/content/svg/document/src/SVGDocument.cpp index 1c4820c1eec8..c5280aef7958 100644 --- a/content/svg/document/src/SVGDocument.cpp +++ b/content/svg/document/src/SVGDocument.cpp @@ -4,7 +4,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/SVGDocument.h" + +#include "mozilla/css/Loader.h" +#include "nsICategoryManager.h" +#include "nsISimpleEnumerator.h" +#include "nsIStyleSheetService.h" +#include "nsISupportsPrimitives.h" #include "nsLayoutStylesheetCache.h" +#include "nsNetUtil.h" +#include "nsServiceManagerUtils.h" #include "nsString.h" #include "nsLiteralString.h" #include "nsIDOMSVGElement.h" @@ -12,6 +20,7 @@ #include "nsSVGElement.h" #include "mozilla/dom/SVGDocumentBinding.h" +using namespace mozilla::css; using namespace mozilla::dom; namespace mozilla { @@ -78,6 +87,59 @@ SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded() mHasLoadedNonSVGUserAgentStyleSheets = true; + if (IsBeingUsedAsImage()) { + // nsDocumentViewer::CreateStyleSet skipped loading all user-agent/user + // style sheets in this case, but we'll need B2G/Fennec/Metro's + // content.css. We could load all the sheets registered with the + // nsIStyleSheetService (and maybe we should) but most likely it isn't + // desirable or necessary for foreignObject in SVG-as-an-image. Instead we + // only load the "agent-style-sheets" that nsStyleSheetService::Init() + // pulls in from the category manager. That keeps memory use of + // SVG-as-an-image down. + // + // We do this before adding UASheet() etc. below because + // EnsureOnDemandBuiltInUASheet prepends, and B2G/Fennec/Metro's + // content.css must come after UASheet() etc. + nsCOMPtr catMan = + do_GetService(NS_CATEGORYMANAGER_CONTRACTID); + if (catMan) { + nsCOMPtr sheets; + catMan->EnumerateCategory("agent-style-sheets", getter_AddRefs(sheets)); + if (sheets) { + bool hasMore; + while (NS_SUCCEEDED(sheets->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr sheet; + if (NS_FAILED(sheets->GetNext(getter_AddRefs(sheet)))) + break; + + nsCOMPtr icStr = do_QueryInterface(sheet); + MOZ_ASSERT(icStr, + "category manager entries must be nsISupportsCStrings"); + + nsAutoCString name; + icStr->GetData(name); + + nsXPIDLCString spec; + catMan->GetCategoryEntry("agent-style-sheets", name.get(), + getter_Copies(spec)); + + mozilla::css::Loader* cssLoader = CSSLoader(); + if (cssLoader->GetEnabled()) { + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), spec); + if (uri) { + nsRefPtr cssSheet; + cssLoader->LoadSheetSync(uri, true, true, getter_AddRefs(cssSheet)); + if (cssSheet) { + EnsureOnDemandBuiltInUASheet(cssSheet); + } + } + } + } + } + } + } + EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::NumberControlSheet()); EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::FormsSheet()); EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::HTMLSheet()); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 7bfe52358092..8bf47a442488 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -2188,7 +2188,22 @@ nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument, styleSet->BeginUpdate(); // The document will fill in the document sheets when we create the presshell - + + if (aDocument->IsBeingUsedAsImage()) { + MOZ_ASSERT(aDocument->IsSVG(), + "Do we want to skip most sheets for this new image type?"); + + // SVG-as-an-image must be kept as light and small as possible. We + // deliberately skip loading everything and leave svg.css (and html.css and + // xul.css) to be loaded on-demand. + // XXXjwatt Nothing else is loaded on-demand, but I don't think that + // should matter for SVG-as-an-image. If it does, I want to know why! + + // Caller will handle calling EndUpdate, per contract. + *aStyleSet = styleSet; + return NS_OK; + } + // Handle the user sheets. nsCSSStyleSheet* sheet = nullptr; if (nsContentUtils::IsInChromeDocshell(aDocument)) { diff --git a/layout/base/nsStyleSheetService.cpp b/layout/base/nsStyleSheetService.cpp index 85f5f815ff6c..aabec1a844bb 100644 --- a/layout/base/nsStyleSheetService.cpp +++ b/layout/base/nsStyleSheetService.cpp @@ -97,6 +97,9 @@ nsStyleSheetService::FindSheetByURI(const nsCOMArray &sheets, nsresult nsStyleSheetService::Init() { + // If you make changes here, consider whether + // SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded should be updated too. + // Child processes get their style sheets from the ContentParent. if (XRE_GetProcessType() == GeckoProcessType_Content) { return NS_OK;