diff options
Diffstat (limited to 'dom/svg/SVGDocument.cpp')
-rw-r--r-- | dom/svg/SVGDocument.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/dom/svg/SVGDocument.cpp b/dom/svg/SVGDocument.cpp new file mode 100644 index 000000000..f992e52f5 --- /dev/null +++ b/dom/svg/SVGDocument.cpp @@ -0,0 +1,179 @@ +/* -*- 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 "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" +#include "mozilla/dom/Element.h" +#include "nsSVGElement.h" +#include "mozilla/StyleSheet.h" +#include "mozilla/StyleSheetInlines.h" + +using namespace mozilla::css; +using namespace mozilla::dom; + +namespace mozilla { +namespace dom { + +//---------------------------------------------------------------------- +// Implementation + +//---------------------------------------------------------------------- +// nsISupports methods: + +nsresult +SVGDocument::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify) +{ + if (aKid->IsElement() && !aKid->IsSVGElement()) { + // We can get here when well formed XML with a non-SVG root element is + // served with the SVG MIME type, for example. In that case we need to load + // the non-SVG UA sheets or else we can get bugs like bug 1016145. Note + // that we have to do this _before_ the XMLDocument::InsertChildAt call, + // since that can try to construct frames, and we need to have the sheets + // loaded by then. + EnsureNonSVGUserAgentStyleSheetsLoaded(); + } + + return XMLDocument::InsertChildAt(aKid, aIndex, aNotify); +} + +nsresult +SVGDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const +{ + NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager, + "Can't import this document into another document!"); + + RefPtr<SVGDocument> clone = new SVGDocument(); + nsresult rv = CloneDocHelper(clone.get()); + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(clone.get(), aResult); +} + +void +SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded() +{ + if (mHasLoadedNonSVGUserAgentStyleSheets) { + return; + } + + if (IsStaticDocument()) { + // If we're a static clone of a document, then + // nsIDocument::CreateStaticClone will handle cloning the original + // document's sheets, including the on-demand non-SVG UA sheets, + // for us. + return; + } + + mHasLoadedNonSVGUserAgentStyleSheets = true; + + BeginUpdate(UPDATE_STYLE); + + if (IsBeingUsedAsImage()) { + // nsDocumentViewer::CreateStyleSet skipped loading all user-agent/user + // style sheets in this case, but we'll need B2G/Fennec'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's + // content.css must come after UASheet() etc. + nsCOMPtr<nsICategoryManager> catMan = + do_GetService(NS_CATEGORYMANAGER_CONTRACTID); + if (catMan) { + nsCOMPtr<nsISimpleEnumerator> sheets; + catMan->EnumerateCategory("agent-style-sheets", getter_AddRefs(sheets)); + if (sheets) { + bool hasMore; + while (NS_SUCCEEDED(sheets->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr<nsISupports> sheet; + if (NS_FAILED(sheets->GetNext(getter_AddRefs(sheet)))) + break; + + nsCOMPtr<nsISupportsCString> 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<nsIURI> uri; + NS_NewURI(getter_AddRefs(uri), spec); + if (uri) { + RefPtr<StyleSheet> sheet; + cssLoader->LoadSheetSync(uri, + mozilla::css::eAgentSheetFeatures, + true, &sheet); + if (sheet) { + EnsureOnDemandBuiltInUASheet(sheet); + } + } + } + } + } + } + } + + auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType()); + + StyleSheet* sheet = cache->NumberControlSheet(); + if (sheet) { + // number-control.css can be behind a pref + EnsureOnDemandBuiltInUASheet(sheet); + } + EnsureOnDemandBuiltInUASheet(cache->FormsSheet()); + EnsureOnDemandBuiltInUASheet(cache->CounterStylesSheet()); + EnsureOnDemandBuiltInUASheet(cache->HTMLSheet()); + if (nsLayoutUtils::ShouldUseNoFramesSheet(this)) { + EnsureOnDemandBuiltInUASheet(cache->NoFramesSheet()); + } + if (nsLayoutUtils::ShouldUseNoScriptSheet(this)) { + EnsureOnDemandBuiltInUASheet(cache->NoScriptSheet()); + } + EnsureOnDemandBuiltInUASheet(cache->UASheet()); + + EndUpdate(UPDATE_STYLE); +} + +} // namespace dom +} // namespace mozilla + +//////////////////////////////////////////////////////////////////////// +// Exported creation functions + +nsresult +NS_NewSVGDocument(nsIDocument** aInstancePtrResult) +{ + RefPtr<SVGDocument> doc = new SVGDocument(); + + nsresult rv = doc->Init(); + if (NS_FAILED(rv)) { + return rv; + } + + doc.forget(aInstancePtrResult); + return rv; +} |