SVGDocument.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/SVGDocument.h"
  6. #include "mozilla/css/Loader.h"
  7. #include "nsICategoryManager.h"
  8. #include "nsISimpleEnumerator.h"
  9. #include "nsIStyleSheetService.h"
  10. #include "nsISupportsPrimitives.h"
  11. #include "nsLayoutStylesheetCache.h"
  12. #include "nsNetUtil.h"
  13. #include "nsServiceManagerUtils.h"
  14. #include "nsString.h"
  15. #include "nsLiteralString.h"
  16. #include "nsIDOMSVGElement.h"
  17. #include "mozilla/dom/Element.h"
  18. #include "nsSVGElement.h"
  19. #include "mozilla/StyleSheet.h"
  20. #include "mozilla/StyleSheetInlines.h"
  21. #include "nsContentUtils.h"
  22. #include "nsLayoutUtils.h"
  23. using namespace mozilla::css;
  24. using namespace mozilla::dom;
  25. namespace mozilla {
  26. namespace dom {
  27. //----------------------------------------------------------------------
  28. // Implementation
  29. //----------------------------------------------------------------------
  30. // nsISupports methods:
  31. nsresult
  32. SVGDocument::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify)
  33. {
  34. if (aKid->IsElement() && !aKid->IsSVGElement()) {
  35. // We can get here when well formed XML with a non-SVG root element is
  36. // served with the SVG MIME type, for example. In that case we need to load
  37. // the non-SVG UA sheets or else we can get bugs like bug 1016145. Note
  38. // that we have to do this _before_ the XMLDocument::InsertChildAt call,
  39. // since that can try to construct frames, and we need to have the sheets
  40. // loaded by then.
  41. EnsureNonSVGUserAgentStyleSheetsLoaded();
  42. }
  43. return XMLDocument::InsertChildAt(aKid, aIndex, aNotify);
  44. }
  45. nsresult
  46. SVGDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
  47. {
  48. NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
  49. "Can't import this document into another document!");
  50. RefPtr<SVGDocument> clone = new SVGDocument();
  51. nsresult rv = CloneDocHelper(clone.get());
  52. NS_ENSURE_SUCCESS(rv, rv);
  53. return CallQueryInterface(clone.get(), aResult);
  54. }
  55. void
  56. SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded()
  57. {
  58. if (mHasLoadedNonSVGUserAgentStyleSheets) {
  59. return;
  60. }
  61. if (IsStaticDocument()) {
  62. // If we're a static clone of a document, then
  63. // nsIDocument::CreateStaticClone will handle cloning the original
  64. // document's sheets, including the on-demand non-SVG UA sheets,
  65. // for us.
  66. return;
  67. }
  68. mHasLoadedNonSVGUserAgentStyleSheets = true;
  69. BeginUpdate(UPDATE_STYLE);
  70. if (IsBeingUsedAsImage()) {
  71. // nsDocumentViewer::CreateStyleSet skipped loading all user-agent/user
  72. // style sheets in this case, but we'll need B2G/Fennec's
  73. // content.css. We could load all the sheets registered with the
  74. // nsIStyleSheetService (and maybe we should) but most likely it isn't
  75. // desirable or necessary for foreignObject in SVG-as-an-image. Instead we
  76. // only load the "agent-style-sheets" that nsStyleSheetService::Init()
  77. // pulls in from the category manager. That keeps memory use of
  78. // SVG-as-an-image down.
  79. //
  80. // We do this before adding UASheet() etc. below because
  81. // EnsureOnDemandBuiltInUASheet prepends, and B2G/Fennec's
  82. // content.css must come after UASheet() etc.
  83. nsCOMPtr<nsICategoryManager> catMan =
  84. do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
  85. if (catMan) {
  86. nsCOMPtr<nsISimpleEnumerator> sheets;
  87. catMan->EnumerateCategory("agent-style-sheets", getter_AddRefs(sheets));
  88. if (sheets) {
  89. bool hasMore;
  90. while (NS_SUCCEEDED(sheets->HasMoreElements(&hasMore)) && hasMore) {
  91. nsCOMPtr<nsISupports> sheet;
  92. if (NS_FAILED(sheets->GetNext(getter_AddRefs(sheet))))
  93. break;
  94. nsCOMPtr<nsISupportsCString> icStr = do_QueryInterface(sheet);
  95. MOZ_ASSERT(icStr,
  96. "category manager entries must be nsISupportsCStrings");
  97. nsAutoCString name;
  98. icStr->GetData(name);
  99. nsXPIDLCString spec;
  100. catMan->GetCategoryEntry("agent-style-sheets", name.get(),
  101. getter_Copies(spec));
  102. mozilla::css::Loader* cssLoader = CSSLoader();
  103. if (cssLoader->GetEnabled()) {
  104. nsCOMPtr<nsIURI> uri;
  105. NS_NewURI(getter_AddRefs(uri), spec);
  106. if (uri) {
  107. RefPtr<StyleSheet> sheet;
  108. cssLoader->LoadSheetSync(uri,
  109. mozilla::css::eAgentSheetFeatures,
  110. true, &sheet);
  111. if (sheet) {
  112. EnsureOnDemandBuiltInUASheet(sheet);
  113. }
  114. }
  115. }
  116. }
  117. }
  118. }
  119. }
  120. auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType());
  121. StyleSheet* sheet = cache->NumberControlSheet();
  122. if (sheet) {
  123. // number-control.css can be behind a pref
  124. EnsureOnDemandBuiltInUASheet(sheet);
  125. }
  126. EnsureOnDemandBuiltInUASheet(cache->FormsSheet());
  127. EnsureOnDemandBuiltInUASheet(cache->CounterStylesSheet());
  128. EnsureOnDemandBuiltInUASheet(cache->HTMLSheet());
  129. if (nsLayoutUtils::ShouldUseNoFramesSheet(this)) {
  130. EnsureOnDemandBuiltInUASheet(cache->NoFramesSheet());
  131. }
  132. if (nsLayoutUtils::ShouldUseNoScriptSheet(this)) {
  133. EnsureOnDemandBuiltInUASheet(cache->NoScriptSheet());
  134. }
  135. EnsureOnDemandBuiltInUASheet(cache->UASheet());
  136. EndUpdate(UPDATE_STYLE);
  137. }
  138. } // namespace dom
  139. } // namespace mozilla
  140. ////////////////////////////////////////////////////////////////////////
  141. // Exported creation functions
  142. nsresult
  143. NS_NewSVGDocument(nsIDocument** aInstancePtrResult)
  144. {
  145. RefPtr<SVGDocument> doc = new SVGDocument();
  146. nsresult rv = doc->Init();
  147. if (NS_FAILED(rv)) {
  148. return rv;
  149. }
  150. doc.forget(aInstancePtrResult);
  151. return rv;
  152. }