1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Jonas Sicking (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsIDOMLinkStyle.h"
40 : #include "nsIDOMStyleSheet.h"
41 : #include "nsIDocument.h"
42 : #include "nsIStyleSheet.h"
43 : #include "nsIURI.h"
44 : #include "nsStyleLinkElement.h"
45 : #include "nsNetUtil.h"
46 : #include "nsXMLProcessingInstruction.h"
47 : #include "nsUnicharUtils.h"
48 : #include "nsGkAtoms.h"
49 : #include "nsThreadUtils.h"
50 : #include "nsContentUtils.h"
51 :
52 : class nsXMLStylesheetPI : public nsXMLProcessingInstruction,
53 : public nsStyleLinkElement
54 : {
55 : public:
56 : nsXMLStylesheetPI(already_AddRefed<nsINodeInfo> aNodeInfo, const nsAString& aData);
57 : virtual ~nsXMLStylesheetPI();
58 :
59 : // nsISupports
60 : NS_DECL_ISUPPORTS_INHERITED
61 :
62 : // nsIDOMNode
63 : NS_IMETHOD SetNodeValue(const nsAString& aData);
64 :
65 : // nsIContent
66 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
67 : nsIContent* aBindingParent,
68 : bool aCompileEventHandlers);
69 : virtual void UnbindFromTree(bool aDeep = true,
70 : bool aNullParent = true);
71 :
72 : // nsIStyleSheetLinkingElement
73 : virtual void OverrideBaseURI(nsIURI* aNewBaseURI);
74 :
75 : // nsStyleLinkElement
76 : NS_IMETHOD GetCharset(nsAString& aCharset);
77 :
78 : virtual nsXPCClassInfo* GetClassInfo();
79 : protected:
80 : nsCOMPtr<nsIURI> mOverriddenBaseURI;
81 :
82 : already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline);
83 : void GetStyleSheetInfo(nsAString& aTitle,
84 : nsAString& aType,
85 : nsAString& aMedia,
86 : bool* aIsAlternate);
87 : virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
88 : bool aCloneText) const;
89 : };
90 :
91 : // nsISupports implementation
92 :
93 0 : DOMCI_NODE_DATA(XMLStylesheetProcessingInstruction, nsXMLStylesheetPI)
94 :
95 1591 : NS_INTERFACE_TABLE_HEAD(nsXMLStylesheetPI)
96 1591 : NS_NODE_INTERFACE_TABLE4(nsXMLStylesheetPI, nsIDOMNode,
97 : nsIDOMProcessingInstruction, nsIDOMLinkStyle,
98 : nsIStyleSheetLinkingElement)
99 1529 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XMLStylesheetProcessingInstruction)
100 1529 : NS_INTERFACE_MAP_END_INHERITING(nsXMLProcessingInstruction)
101 :
102 682 : NS_IMPL_ADDREF_INHERITED(nsXMLStylesheetPI, nsXMLProcessingInstruction)
103 682 : NS_IMPL_RELEASE_INHERITED(nsXMLStylesheetPI, nsXMLProcessingInstruction)
104 :
105 :
106 62 : nsXMLStylesheetPI::nsXMLStylesheetPI(already_AddRefed<nsINodeInfo> aNodeInfo,
107 : const nsAString& aData)
108 62 : : nsXMLProcessingInstruction(aNodeInfo, aData)
109 : {
110 62 : }
111 :
112 124 : nsXMLStylesheetPI::~nsXMLStylesheetPI()
113 : {
114 248 : }
115 :
116 : // nsIContent
117 :
118 : nsresult
119 62 : nsXMLStylesheetPI::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
120 : nsIContent* aBindingParent,
121 : bool aCompileEventHandlers)
122 : {
123 : nsresult rv = nsXMLProcessingInstruction::BindToTree(aDocument, aParent,
124 : aBindingParent,
125 62 : aCompileEventHandlers);
126 62 : NS_ENSURE_SUCCESS(rv, rv);
127 :
128 62 : void (nsXMLStylesheetPI::*update)() = &nsXMLStylesheetPI::UpdateStyleSheetInternal;
129 62 : nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, update));
130 :
131 62 : return rv;
132 : }
133 :
134 : void
135 62 : nsXMLStylesheetPI::UnbindFromTree(bool aDeep, bool aNullParent)
136 : {
137 124 : nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
138 :
139 62 : nsXMLProcessingInstruction::UnbindFromTree(aDeep, aNullParent);
140 62 : UpdateStyleSheetInternal(oldDoc);
141 62 : }
142 :
143 : // nsIDOMNode
144 :
145 : NS_IMETHODIMP
146 0 : nsXMLStylesheetPI::SetNodeValue(const nsAString& aNodeValue)
147 : {
148 0 : nsresult rv = nsGenericDOMDataNode::SetNodeValue(aNodeValue);
149 0 : if (NS_SUCCEEDED(rv)) {
150 0 : UpdateStyleSheetInternal(nsnull, true);
151 : }
152 0 : return rv;
153 : }
154 :
155 : // nsStyleLinkElement
156 :
157 : NS_IMETHODIMP
158 0 : nsXMLStylesheetPI::GetCharset(nsAString& aCharset)
159 : {
160 0 : return GetAttrValue(nsGkAtoms::charset, aCharset) ? NS_OK : NS_ERROR_FAILURE;
161 : }
162 :
163 : /* virtual */ void
164 0 : nsXMLStylesheetPI::OverrideBaseURI(nsIURI* aNewBaseURI)
165 : {
166 0 : mOverriddenBaseURI = aNewBaseURI;
167 0 : }
168 :
169 : already_AddRefed<nsIURI>
170 0 : nsXMLStylesheetPI::GetStyleSheetURL(bool* aIsInline)
171 : {
172 0 : *aIsInline = false;
173 :
174 0 : nsAutoString href;
175 0 : if (!GetAttrValue(nsGkAtoms::href, href)) {
176 0 : return nsnull;
177 : }
178 :
179 : nsIURI *baseURL;
180 0 : nsCAutoString charset;
181 0 : nsIDocument *document = OwnerDoc();
182 : baseURL = mOverriddenBaseURI ?
183 0 : mOverriddenBaseURI.get() :
184 0 : document->GetDocBaseURI();
185 0 : charset = document->GetDocumentCharacterSet();
186 :
187 0 : nsCOMPtr<nsIURI> aURI;
188 0 : NS_NewURI(getter_AddRefs(aURI), href, charset.get(), baseURL);
189 0 : return aURI.forget();
190 : }
191 :
192 : void
193 0 : nsXMLStylesheetPI::GetStyleSheetInfo(nsAString& aTitle,
194 : nsAString& aType,
195 : nsAString& aMedia,
196 : bool* aIsAlternate)
197 : {
198 0 : aTitle.Truncate();
199 0 : aType.Truncate();
200 0 : aMedia.Truncate();
201 0 : *aIsAlternate = false;
202 :
203 : // xml-stylesheet PI is special only in prolog
204 0 : if (!nsContentUtils::InProlog(this)) {
205 0 : return;
206 : }
207 :
208 0 : nsAutoString data;
209 0 : GetData(data);
210 :
211 0 : nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, aTitle);
212 :
213 0 : nsAutoString alternate;
214 : nsContentUtils::GetPseudoAttributeValue(data,
215 : nsGkAtoms::alternate,
216 0 : alternate);
217 :
218 : // if alternate, does it have title?
219 0 : if (alternate.EqualsLiteral("yes")) {
220 0 : if (aTitle.IsEmpty()) { // alternates must have title
221 : return;
222 : }
223 :
224 0 : *aIsAlternate = true;
225 : }
226 :
227 0 : nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, aMedia);
228 :
229 0 : nsAutoString type;
230 0 : nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
231 :
232 0 : nsAutoString mimeType, notUsed;
233 0 : nsContentUtils::SplitMimeType(type, mimeType, notUsed);
234 0 : if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
235 0 : aType.Assign(type);
236 : return;
237 : }
238 :
239 : // If we get here we assume that we're loading a css file, so set the
240 : // type to 'text/css'
241 0 : aType.AssignLiteral("text/css");
242 :
243 : return;
244 : }
245 :
246 : nsGenericDOMDataNode*
247 0 : nsXMLStylesheetPI::CloneDataNode(nsINodeInfo *aNodeInfo, bool aCloneText) const
248 : {
249 0 : nsAutoString data;
250 0 : nsGenericDOMDataNode::GetData(data);
251 0 : nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
252 0 : return new nsXMLStylesheetPI(ni.forget(), data);
253 : }
254 :
255 : nsresult
256 62 : NS_NewXMLStylesheetProcessingInstruction(nsIContent** aInstancePtrResult,
257 : nsNodeInfoManager *aNodeInfoManager,
258 : const nsAString& aData)
259 : {
260 62 : NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager");
261 :
262 62 : *aInstancePtrResult = nsnull;
263 :
264 124 : nsCOMPtr<nsINodeInfo> ni;
265 : ni = aNodeInfoManager->GetNodeInfo(nsGkAtoms::processingInstructionTagName,
266 : nsnull, kNameSpaceID_None,
267 : nsIDOMNode::PROCESSING_INSTRUCTION_NODE,
268 62 : nsGkAtoms::xml_stylesheet);
269 62 : NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
270 :
271 124 : nsXMLStylesheetPI *instance = new nsXMLStylesheetPI(ni.forget(), aData);
272 62 : if (!instance) {
273 0 : return NS_ERROR_OUT_OF_MEMORY;
274 : }
275 :
276 62 : NS_ADDREF(*aInstancePtrResult = instance);
277 :
278 62 : return NS_OK;
279 : }
|