2 * Copyright (C) 2000 Peter Kelly (pmk@post.com)
3 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "ProcessingInstruction.h"
24 #include "CSSStyleSheet.h"
25 #include "CachedCSSStyleSheet.h"
26 #include "CachedXSLStyleSheet.h"
28 #include "DocLoader.h"
29 #include "ExceptionCode.h"
31 #include "FrameLoader.h"
32 #include "XSLStyleSheet.h"
33 #include "XMLTokenizer.h" // for parseAttributes()
34 #include "MediaList.h"
38 ProcessingInstruction::ProcessingInstruction(Document
* doc
)
49 ProcessingInstruction::ProcessingInstruction(Document
* doc
, const String
& target
, const String
& data
)
62 ProcessingInstruction::~ProcessingInstruction()
65 m_cachedSheet
->removeClient(this);
68 void ProcessingInstruction::setData(const String
& data
, ExceptionCode
&)
70 int oldLength
= m_data
.length();
72 document()->textRemoved(this, 0, oldLength
);
75 String
ProcessingInstruction::nodeName() const
80 Node::NodeType
ProcessingInstruction::nodeType() const
82 return PROCESSING_INSTRUCTION_NODE
;
85 String
ProcessingInstruction::nodeValue() const
90 void ProcessingInstruction::setNodeValue(const String
& nodeValue
, ExceptionCode
& ec
)
92 // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
93 setData(nodeValue
, ec
);
96 PassRefPtr
<Node
> ProcessingInstruction::cloneNode(bool /*deep*/)
98 // ### copy m_localHref
99 return new ProcessingInstruction(document(), m_target
, m_data
);
103 bool ProcessingInstruction::childTypeAllowed(NodeType
)
108 void ProcessingInstruction::checkStyleSheet()
110 if (m_target
== "xml-stylesheet" && document()->frame() && parentNode() == document()) {
111 // see http://www.w3.org/TR/xml-stylesheet/
112 // ### support stylesheet included in a fragment of this (or another) document
113 // ### make sure this gets called when adding from javascript
115 const HashMap
<String
, String
> attrs
= parseAttributes(m_data
, attrsOk
);
118 HashMap
<String
, String
>::const_iterator i
= attrs
.find("type");
120 if (i
!= attrs
.end())
123 bool isCSS
= type
.isEmpty() || type
== "text/css";
125 m_isXSL
= (type
== "text/xml" || type
== "text/xsl" || type
== "application/xml" ||
126 type
== "application/xhtml+xml" || type
== "application/rss+xml" || type
== "application/atom=xml");
127 if (!isCSS
&& !m_isXSL
)
133 String href
= attrs
.get("href");
134 String alternate
= attrs
.get("alternate");
135 m_alternate
= alternate
== "yes";
136 m_title
= attrs
.get("title");
137 m_media
= attrs
.get("media");
139 if (href
.length() > 1) {
140 if (href
[0] == '#') {
141 m_localHref
= href
.substring(1);
143 // We need to make a synthetic XSLStyleSheet that is embedded. It needs to be able
144 // to kick off import/include loads that can hang off some parent sheet.
146 m_sheet
= XSLStyleSheet::createEmbedded(this, m_localHref
);
154 document()->addPendingSheet();
156 m_cachedSheet
->removeClient(this);
159 m_cachedSheet
= document()->docLoader()->requestXSLStyleSheet(document()->completeURL(href
).string());
163 String charset
= attrs
.get("charset");
164 if (charset
.isEmpty())
165 charset
= document()->frame()->loader()->encoding();
167 m_cachedSheet
= document()->docLoader()->requestCSSStyleSheet(document()->completeURL(href
).string(), charset
);
170 m_cachedSheet
->addClient(this);
176 bool ProcessingInstruction::isLoading() const
182 return m_sheet
->isLoading();
185 bool ProcessingInstruction::sheetLoaded()
188 document()->removePendingSheet();
194 void ProcessingInstruction::setCSSStyleSheet(const String
& url
, const String
& charset
, const CachedCSSStyleSheet
* sheet
)
199 RefPtr
<CSSStyleSheet
> newSheet
= CSSStyleSheet::create(this, url
, charset
);
201 parseStyleSheet(sheet
->sheetText());
202 newSheet
->setTitle(m_title
);
203 newSheet
->setMedia(MediaList::create(newSheet
.get(), m_media
));
204 newSheet
->setDisabled(m_alternate
);
208 void ProcessingInstruction::setXSLStyleSheet(const String
& url
, const String
& sheet
)
211 m_sheet
= XSLStyleSheet::create(this, url
);
212 parseStyleSheet(sheet
);
216 void ProcessingInstruction::parseStyleSheet(const String
& sheet
)
218 m_sheet
->parseString(sheet
, true);
220 m_cachedSheet
->removeClient(this);
224 m_sheet
->checkLoaded();
227 void ProcessingInstruction::setCSSStyleSheet(PassRefPtr
<CSSStyleSheet
> sheet
)
229 ASSERT(!m_cachedSheet
);
232 m_sheet
->setTitle(m_title
);
233 m_sheet
->setDisabled(m_alternate
);
236 bool ProcessingInstruction::offsetInCharacters() const
241 int ProcessingInstruction::maxCharacterOffset() const
243 return static_cast<int>(m_data
.length());
246 void ProcessingInstruction::getSubresourceAttributeStrings(Vector
<String
>& urls
) const
251 urls
.append(sheet()->href());
254 void ProcessingInstruction::insertedIntoDocument()
256 ContainerNode::insertedIntoDocument();
257 document()->addStyleSheetCandidateNode(this, m_createdByParser
);
261 void ProcessingInstruction::removedFromDocument()
263 ContainerNode::removedFromDocument();
265 if (document()->renderer())
266 document()->removeStyleSheetCandidateNode(this);
268 // FIXME: It's terrible to do a synchronous update of the style selector just because a <style> or <link> element got removed.
270 document()->updateStyleSelector();
273 void ProcessingInstruction::finishParsingChildren()
275 m_createdByParser
= false;
276 ContainerNode::finishParsingChildren();