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 "XMLStylesheetProcessingInstruction.h"
8 
9 #include "mozilla/dom/Document.h"
10 #include "mozilla/dom/ReferrerInfo.h"
11 #include "nsContentUtils.h"
12 #include "nsNetUtil.h"
13 
14 namespace mozilla {
15 namespace dom {
16 
17 // nsISupports implementation
18 
19 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
20     XMLStylesheetProcessingInstruction, ProcessingInstruction)
21 
22 NS_IMPL_CYCLE_COLLECTION_CLASS(XMLStylesheetProcessingInstruction)
23 
24 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
25     XMLStylesheetProcessingInstruction, ProcessingInstruction)
26   tmp->LinkStyle::Traverse(cb);
27 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
28 
29 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(
30     XMLStylesheetProcessingInstruction, ProcessingInstruction)
31   tmp->LinkStyle::Unlink();
32 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
33 
34 XMLStylesheetProcessingInstruction::~XMLStylesheetProcessingInstruction() =
35     default;
36 
37 // nsIContent
38 
BindToTree(BindContext & aContext,nsINode & aParent)39 nsresult XMLStylesheetProcessingInstruction::BindToTree(BindContext& aContext,
40                                                         nsINode& aParent) {
41   nsresult rv = ProcessingInstruction::BindToTree(aContext, aParent);
42   NS_ENSURE_SUCCESS(rv, rv);
43 
44   void (XMLStylesheetProcessingInstruction::*update)() =
45       &XMLStylesheetProcessingInstruction::UpdateStyleSheetInternal;
46   nsContentUtils::AddScriptRunner(NewRunnableMethod(
47       "dom::XMLStylesheetProcessingInstruction::BindToTree", this, update));
48 
49   return rv;
50 }
51 
UnbindFromTree(bool aNullParent)52 void XMLStylesheetProcessingInstruction::UnbindFromTree(bool aNullParent) {
53   nsCOMPtr<Document> oldDoc = GetUncomposedDoc();
54 
55   ProcessingInstruction::UnbindFromTree(aNullParent);
56   Unused << UpdateStyleSheetInternal(oldDoc, nullptr);
57 }
58 
59 // nsINode
60 
SetNodeValueInternal(const nsAString & aNodeValue,ErrorResult & aError)61 void XMLStylesheetProcessingInstruction::SetNodeValueInternal(
62     const nsAString& aNodeValue, ErrorResult& aError) {
63   CharacterData::SetNodeValueInternal(aNodeValue, aError);
64   if (!aError.Failed()) {
65     Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
66   }
67 }
68 
69 // LinkStyle
70 
GetCharset(nsAString & aCharset)71 void XMLStylesheetProcessingInstruction::GetCharset(nsAString& aCharset) {
72   if (!GetAttrValue(nsGkAtoms::charset, aCharset)) {
73     aCharset.Truncate();
74   }
75 }
76 
OverrideBaseURI(nsIURI * aNewBaseURI)77 void XMLStylesheetProcessingInstruction::OverrideBaseURI(nsIURI* aNewBaseURI) {
78   mOverriddenBaseURI = aNewBaseURI;
79 }
80 
81 Maybe<LinkStyle::SheetInfo>
GetStyleSheetInfo()82 XMLStylesheetProcessingInstruction::GetStyleSheetInfo() {
83   // xml-stylesheet PI is special only in prolog
84   if (!nsContentUtils::InProlog(this)) {
85     return Nothing();
86   }
87 
88   nsAutoString href;
89   if (!GetAttrValue(nsGkAtoms::href, href)) {
90     return Nothing();
91   }
92 
93   nsAutoString data;
94   GetData(data);
95 
96   nsAutoString title;
97   nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, title);
98 
99   nsAutoString alternateAttr;
100   nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::alternate,
101                                           alternateAttr);
102 
103   bool alternate = alternateAttr.EqualsLiteral("yes");
104   if (alternate && title.IsEmpty()) {
105     // alternates must have title
106     return Nothing();
107   }
108 
109   nsAutoString media;
110   nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, media);
111 
112   // Make sure the type handling here matches
113   // nsXMLContentSink::HandleProcessingInstruction
114   nsAutoString type;
115   nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
116 
117   nsAutoString mimeType, notUsed;
118   nsContentUtils::SplitMimeType(type, mimeType, notUsed);
119   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
120     return Nothing();
121   }
122 
123   Document* doc = OwnerDoc();
124   nsIURI* baseURL =
125       mOverriddenBaseURI ? mOverriddenBaseURI.get() : doc->GetDocBaseURI();
126   auto encoding = doc->GetDocumentCharacterSet();
127   nsCOMPtr<nsIURI> uri;
128   NS_NewURI(getter_AddRefs(uri), href, encoding, baseURL);
129 
130   return Some(SheetInfo{
131       *doc,
132       this,
133       uri.forget(),
134       nullptr,
135       MakeAndAddRef<ReferrerInfo>(*doc),
136       CORS_NONE,
137       title,
138       media,
139       /* integrity = */ u""_ns,
140       /* nonce = */ u""_ns,
141       alternate ? HasAlternateRel::Yes : HasAlternateRel::No,
142       IsInline::No,
143       IsExplicitlyEnabled::No,
144   });
145 }
146 
147 already_AddRefed<CharacterData>
CloneDataNode(mozilla::dom::NodeInfo * aNodeInfo,bool aCloneText) const148 XMLStylesheetProcessingInstruction::CloneDataNode(
149     mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const {
150   nsAutoString data;
151   GetData(data);
152   RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
153   auto* nim = ni->NodeInfoManager();
154   return do_AddRef(new (nim)
155                        XMLStylesheetProcessingInstruction(ni.forget(), data));
156 }
157 
158 }  // namespace dom
159 }  // namespace mozilla
160