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