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) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Daniel Glazman <glazman@netscape.com>
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 : #include "nsIDOMHTMLStyleElement.h"
39 : #include "nsIDOMLinkStyle.h"
40 : #include "nsIDOMEventTarget.h"
41 : #include "nsGenericHTMLElement.h"
42 : #include "nsGkAtoms.h"
43 : #include "nsStyleConsts.h"
44 : #include "nsIDOMStyleSheet.h"
45 : #include "nsIStyleSheet.h"
46 : #include "nsStyleLinkElement.h"
47 : #include "nsNetUtil.h"
48 : #include "nsIDocument.h"
49 : #include "nsUnicharUtils.h"
50 : #include "nsThreadUtils.h"
51 : #include "nsContentUtils.h"
52 :
53 : class nsHTMLStyleElement : public nsGenericHTMLElement,
54 : public nsIDOMHTMLStyleElement,
55 : public nsStyleLinkElement,
56 : public nsStubMutationObserver
57 : {
58 : public:
59 : nsHTMLStyleElement(already_AddRefed<nsINodeInfo> aNodeInfo);
60 : virtual ~nsHTMLStyleElement();
61 :
62 : // nsISupports
63 : NS_DECL_ISUPPORTS_INHERITED
64 :
65 : // nsIDOMNode
66 0 : NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
67 :
68 : // nsIDOMElement
69 0 : NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
70 :
71 : // nsIDOMHTMLElement
72 0 : NS_FORWARD_NSIDOMHTMLELEMENT_BASIC(nsGenericHTMLElement::)
73 0 : NS_SCRIPTABLE NS_IMETHOD Click() {
74 0 : return nsGenericHTMLElement::Click();
75 : }
76 0 : NS_SCRIPTABLE NS_IMETHOD GetTabIndex(PRInt32* aTabIndex) {
77 0 : return nsGenericHTMLElement::GetTabIndex(aTabIndex);
78 : }
79 0 : NS_SCRIPTABLE NS_IMETHOD SetTabIndex(PRInt32 aTabIndex) {
80 0 : return nsGenericHTMLElement::SetTabIndex(aTabIndex);
81 : }
82 0 : NS_SCRIPTABLE NS_IMETHOD Focus() {
83 0 : return nsGenericHTMLElement::Focus();
84 : }
85 0 : NS_SCRIPTABLE NS_IMETHOD GetDraggable(bool* aDraggable) {
86 0 : return nsGenericHTMLElement::GetDraggable(aDraggable);
87 : }
88 : NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
89 : NS_SCRIPTABLE NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML);
90 :
91 : // nsIDOMHTMLStyleElement
92 : NS_DECL_NSIDOMHTMLSTYLEELEMENT
93 :
94 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
95 : nsIContent* aBindingParent,
96 : bool aCompileEventHandlers);
97 : virtual void UnbindFromTree(bool aDeep = true,
98 : bool aNullParent = true);
99 : nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
100 : const nsAString& aValue, bool aNotify)
101 : {
102 : return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
103 : }
104 : virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
105 : nsIAtom* aPrefix, const nsAString& aValue,
106 : bool aNotify);
107 : virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
108 : bool aNotify);
109 :
110 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
111 :
112 : // nsIMutationObserver
113 : NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
114 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
115 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
116 : NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
117 :
118 : virtual nsXPCClassInfo* GetClassInfo();
119 : protected:
120 : already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline);
121 : void GetStyleSheetInfo(nsAString& aTitle,
122 : nsAString& aType,
123 : nsAString& aMedia,
124 : bool* aIsAlternate);
125 : /**
126 : * Common method to call from the various mutation observer methods.
127 : * aContent is a content node that's either the one that changed or its
128 : * parent; we should only respond to the change if aContent is non-anonymous.
129 : */
130 : void ContentChanged(nsIContent* aContent);
131 : };
132 :
133 :
134 0 : NS_IMPL_NS_NEW_HTML_ELEMENT(Style)
135 :
136 :
137 0 : nsHTMLStyleElement::nsHTMLStyleElement(already_AddRefed<nsINodeInfo> aNodeInfo)
138 0 : : nsGenericHTMLElement(aNodeInfo)
139 : {
140 0 : AddMutationObserver(this);
141 0 : }
142 :
143 0 : nsHTMLStyleElement::~nsHTMLStyleElement()
144 : {
145 0 : }
146 :
147 :
148 0 : NS_IMPL_ADDREF_INHERITED(nsHTMLStyleElement, nsGenericElement)
149 0 : NS_IMPL_RELEASE_INHERITED(nsHTMLStyleElement, nsGenericElement)
150 :
151 :
152 0 : DOMCI_NODE_DATA(HTMLStyleElement, nsHTMLStyleElement)
153 :
154 : // QueryInterface implementation for nsHTMLStyleElement
155 0 : NS_INTERFACE_TABLE_HEAD(nsHTMLStyleElement)
156 0 : NS_HTML_CONTENT_INTERFACE_TABLE4(nsHTMLStyleElement,
157 : nsIDOMHTMLStyleElement,
158 : nsIDOMLinkStyle,
159 : nsIStyleSheetLinkingElement,
160 : nsIMutationObserver)
161 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLStyleElement,
162 : nsGenericHTMLElement)
163 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLStyleElement)
164 :
165 :
166 0 : NS_IMPL_ELEMENT_CLONE(nsHTMLStyleElement)
167 :
168 :
169 : NS_IMETHODIMP
170 0 : nsHTMLStyleElement::GetDisabled(bool* aDisabled)
171 : {
172 0 : nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetStyleSheet());
173 0 : if (!ss) {
174 0 : *aDisabled = false;
175 0 : return NS_OK;
176 : }
177 :
178 0 : return ss->GetDisabled(aDisabled);
179 : }
180 :
181 : NS_IMETHODIMP
182 0 : nsHTMLStyleElement::SetDisabled(bool aDisabled)
183 : {
184 0 : nsCOMPtr<nsIDOMStyleSheet> ss = do_QueryInterface(GetStyleSheet());
185 0 : if (!ss) {
186 0 : return NS_OK;
187 : }
188 :
189 0 : return ss->SetDisabled(aDisabled);
190 : }
191 :
192 0 : NS_IMPL_STRING_ATTR(nsHTMLStyleElement, Media, media)
193 0 : NS_IMPL_STRING_ATTR(nsHTMLStyleElement, Type, type)
194 :
195 : void
196 0 : nsHTMLStyleElement::CharacterDataChanged(nsIDocument* aDocument,
197 : nsIContent* aContent,
198 : CharacterDataChangeInfo* aInfo)
199 : {
200 0 : ContentChanged(aContent);
201 0 : }
202 :
203 : void
204 0 : nsHTMLStyleElement::ContentAppended(nsIDocument* aDocument,
205 : nsIContent* aContainer,
206 : nsIContent* aFirstNewContent,
207 : PRInt32 aNewIndexInContainer)
208 : {
209 0 : ContentChanged(aContainer);
210 0 : }
211 :
212 : void
213 0 : nsHTMLStyleElement::ContentInserted(nsIDocument* aDocument,
214 : nsIContent* aContainer,
215 : nsIContent* aChild,
216 : PRInt32 aIndexInContainer)
217 : {
218 0 : ContentChanged(aChild);
219 0 : }
220 :
221 : void
222 0 : nsHTMLStyleElement::ContentRemoved(nsIDocument* aDocument,
223 : nsIContent* aContainer,
224 : nsIContent* aChild,
225 : PRInt32 aIndexInContainer,
226 : nsIContent* aPreviousSibling)
227 : {
228 0 : ContentChanged(aChild);
229 0 : }
230 :
231 : void
232 0 : nsHTMLStyleElement::ContentChanged(nsIContent* aContent)
233 : {
234 0 : if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
235 0 : UpdateStyleSheetInternal(nsnull);
236 : }
237 0 : }
238 :
239 : nsresult
240 0 : nsHTMLStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
241 : nsIContent* aBindingParent,
242 : bool aCompileEventHandlers)
243 : {
244 : nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
245 : aBindingParent,
246 0 : aCompileEventHandlers);
247 0 : NS_ENSURE_SUCCESS(rv, rv);
248 :
249 0 : void (nsHTMLStyleElement::*update)() = &nsHTMLStyleElement::UpdateStyleSheetInternal;
250 0 : nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, update));
251 :
252 0 : return rv;
253 : }
254 :
255 : void
256 0 : nsHTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
257 : {
258 0 : nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
259 :
260 0 : nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
261 0 : UpdateStyleSheetInternal(oldDoc);
262 0 : }
263 :
264 : nsresult
265 0 : nsHTMLStyleElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
266 : nsIAtom* aPrefix, const nsAString& aValue,
267 : bool aNotify)
268 : {
269 : nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
270 0 : aValue, aNotify);
271 0 : if (NS_SUCCEEDED(rv)) {
272 : UpdateStyleSheetInternal(nsnull,
273 : aNameSpaceID == kNameSpaceID_None &&
274 : (aName == nsGkAtoms::title ||
275 : aName == nsGkAtoms::media ||
276 0 : aName == nsGkAtoms::type));
277 : }
278 :
279 0 : return rv;
280 : }
281 :
282 : nsresult
283 0 : nsHTMLStyleElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
284 : bool aNotify)
285 : {
286 : nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
287 0 : aNotify);
288 0 : if (NS_SUCCEEDED(rv)) {
289 : UpdateStyleSheetInternal(nsnull,
290 : aNameSpaceID == kNameSpaceID_None &&
291 : (aAttribute == nsGkAtoms::title ||
292 : aAttribute == nsGkAtoms::media ||
293 0 : aAttribute == nsGkAtoms::type));
294 : }
295 :
296 0 : return rv;
297 : }
298 :
299 : nsresult
300 0 : nsHTMLStyleElement::GetInnerHTML(nsAString& aInnerHTML)
301 : {
302 0 : nsContentUtils::GetNodeTextContent(this, false, aInnerHTML);
303 0 : return NS_OK;
304 : }
305 :
306 : nsresult
307 0 : nsHTMLStyleElement::SetInnerHTML(const nsAString& aInnerHTML)
308 : {
309 0 : SetEnableUpdates(false);
310 :
311 0 : nsresult rv = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
312 :
313 0 : SetEnableUpdates(true);
314 :
315 0 : UpdateStyleSheetInternal(nsnull);
316 0 : return rv;
317 : }
318 :
319 : already_AddRefed<nsIURI>
320 0 : nsHTMLStyleElement::GetStyleSheetURL(bool* aIsInline)
321 : {
322 0 : *aIsInline = true;
323 0 : return nsnull;
324 : }
325 :
326 : void
327 0 : nsHTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
328 : nsAString& aType,
329 : nsAString& aMedia,
330 : bool* aIsAlternate)
331 : {
332 0 : aTitle.Truncate();
333 0 : aType.Truncate();
334 0 : aMedia.Truncate();
335 0 : *aIsAlternate = false;
336 :
337 0 : nsAutoString title;
338 0 : GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
339 0 : title.CompressWhitespace();
340 0 : aTitle.Assign(title);
341 :
342 0 : GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
343 : // The HTML5 spec is formulated in terms of the CSSOM spec, which specifies
344 : // that media queries should be ASCII lowercased during serialization.
345 0 : nsContentUtils::ASCIIToLower(aMedia);
346 :
347 0 : GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
348 :
349 0 : nsAutoString mimeType;
350 0 : nsAutoString notUsed;
351 0 : nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
352 0 : if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
353 : return;
354 : }
355 :
356 : // If we get here we assume that we're loading a css file, so set the
357 : // type to 'text/css'
358 0 : aType.AssignLiteral("text/css");
359 : }
|