1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "txUnknownHandler.h"
10 #include "mozilla/UniquePtrExtensions.h"
11 #include "nsGkAtoms.h"
12 #include "txExecutionState.h"
13 #include "txStringUtils.h"
14 #include "txStylesheet.h"
16 using mozilla::UniquePtr
;
17 using mozilla::WrapUnique
;
19 txUnknownHandler::txUnknownHandler(txExecutionState
* aEs
)
20 : mEs(aEs
), mFlushed(false) {
21 MOZ_COUNT_CTOR_INHERITED(txUnknownHandler
, txBufferingHandler
);
24 txUnknownHandler::~txUnknownHandler() {
25 MOZ_COUNT_DTOR_INHERITED(txUnknownHandler
, txBufferingHandler
);
28 nsresult
txUnknownHandler::attribute(nsAtom
* aPrefix
, nsAtom
* aLocalName
,
29 nsAtom
* aLowercaseLocalName
, int32_t aNsID
,
30 const nsString
& aValue
) {
32 ? mEs
->mResultHandler
->attribute(
33 aPrefix
, aLocalName
, aLowercaseLocalName
, aNsID
, aValue
)
34 : txBufferingHandler::attribute(
35 aPrefix
, aLocalName
, aLowercaseLocalName
, aNsID
, aValue
);
38 nsresult
txUnknownHandler::attribute(nsAtom
* aPrefix
,
39 const nsAString
& aLocalName
,
41 const nsString
& aValue
) {
42 return mFlushed
? mEs
->mResultHandler
->attribute(aPrefix
, aLocalName
, aNsID
,
44 : txBufferingHandler::attribute(aPrefix
, aLocalName
, aNsID
,
48 nsresult
txUnknownHandler::characters(const nsAString
& aData
, bool aDOE
) {
49 return mFlushed
? mEs
->mResultHandler
->characters(aData
, aDOE
)
50 : txBufferingHandler::characters(aData
, aDOE
);
53 nsresult
txUnknownHandler::comment(const nsString
& aData
) {
54 return mFlushed
? mEs
->mResultHandler
->comment(aData
)
55 : txBufferingHandler::comment(aData
);
58 nsresult
txUnknownHandler::endDocument(nsresult aResult
) {
60 if (NS_FAILED(aResult
)) {
64 // This is an unusual case, no output method has been set and we
65 // didn't create a document element. Switching to XML output mode
68 // Make sure that mEs->mResultHandler == this is true, otherwise we'll
69 // leak mEs->mResultHandler in createHandlerAndFlush.
70 NS_ASSERTION(mEs
->mResultHandler
== this,
71 "We're leaking mEs->mResultHandler.");
73 nsresult rv
= createHandlerAndFlush(false, u
""_ns
, kNameSpaceID_None
);
74 NS_ENSURE_SUCCESS(rv
, rv
);
77 return mEs
->mResultHandler
->endDocument(aResult
);
80 nsresult
txUnknownHandler::endElement() {
81 return mFlushed
? mEs
->mResultHandler
->endElement()
82 : txBufferingHandler::endElement();
85 nsresult
txUnknownHandler::processingInstruction(const nsString
& aTarget
,
86 const nsString
& aData
) {
87 return mFlushed
? mEs
->mResultHandler
->processingInstruction(aTarget
, aData
)
88 : txBufferingHandler::processingInstruction(aTarget
, aData
);
91 nsresult
txUnknownHandler::startDocument() {
92 return mFlushed
? mEs
->mResultHandler
->startDocument()
93 : txBufferingHandler::startDocument();
96 nsresult
txUnknownHandler::startElement(nsAtom
* aPrefix
, nsAtom
* aLocalName
,
97 nsAtom
* aLowercaseLocalName
,
100 // Make sure that mEs->mResultHandler == this is true, otherwise we'll
101 // leak mEs->mResultHandler in createHandlerAndFlush.
102 NS_ASSERTION(mEs
->mResultHandler
== this,
103 "We're leaking mEs->mResultHandler.");
105 RefPtr
<nsAtom
> owner
;
106 if (!aLowercaseLocalName
) {
107 owner
= TX_ToLowerCaseAtom(aLocalName
);
108 NS_ENSURE_TRUE(owner
, NS_ERROR_OUT_OF_MEMORY
);
110 aLowercaseLocalName
= owner
;
113 bool htmlRoot
= aNsID
== kNameSpaceID_None
&& !aPrefix
&&
114 aLowercaseLocalName
== nsGkAtoms::html
;
116 // Use aLocalName and not aLowercaseLocalName in case the output
117 // handler cares about case. For eHTMLOutput the handler will hardcode
119 nsresult rv
= createHandlerAndFlush(
120 htmlRoot
, nsDependentAtomString(aLocalName
), aNsID
);
121 NS_ENSURE_SUCCESS(rv
, rv
);
124 return mEs
->mResultHandler
->startElement(aPrefix
, aLocalName
,
125 aLowercaseLocalName
, aNsID
);
128 nsresult
txUnknownHandler::startElement(nsAtom
* aPrefix
,
129 const nsAString
& aLocalName
,
130 const int32_t aNsID
) {
132 // Make sure that mEs->mResultHandler == this is true, otherwise we'll
133 // leak mEs->mResultHandler in createHandlerAndFlush.
134 NS_ASSERTION(mEs
->mResultHandler
== this,
135 "We're leaking mEs->mResultHandler.");
138 aNsID
== kNameSpaceID_None
&& !aPrefix
&&
139 aLocalName
.Equals(u
"html"_ns
, nsCaseInsensitiveStringComparator
);
140 nsresult rv
= createHandlerAndFlush(htmlRoot
, aLocalName
, aNsID
);
141 NS_ENSURE_SUCCESS(rv
, rv
);
144 return mEs
->mResultHandler
->startElement(aPrefix
, aLocalName
, aNsID
);
147 nsresult
txUnknownHandler::createHandlerAndFlush(bool aHTMLRoot
,
148 const nsAString
& aName
,
149 const int32_t aNsID
) {
150 NS_ENSURE_TRUE(mBuffer
, NS_ERROR_NOT_INITIALIZED
);
152 txOutputFormat format
;
153 format
.merge(*(mEs
->mStylesheet
->getOutputFormat()));
154 if (format
.mMethod
== eMethodNotSet
) {
155 format
.mMethod
= aHTMLRoot
? eHTMLOutput
: eXMLOutput
;
158 UniquePtr
<txAXMLEventHandler
> handler
;
159 nsresult rv
= mEs
->mOutputHandlerFactory
->createHandlerWith(
160 &format
, aName
, aNsID
, getter_Transfers(handler
));
161 NS_ENSURE_SUCCESS(rv
, rv
);
163 mEs
->mOutputHandler
= handler
.get();
164 mEs
->mResultHandler
= handler
.release();
165 // Let the executionstate delete us. We need to stay alive because we might
166 // need to forward hooks to mEs->mResultHandler if someone is currently
167 // flushing a buffer to mEs->mResultHandler.
168 mEs
->mObsoleteHandler
= WrapUnique(this);
172 // Let go of out buffer as soon as we're done flushing it, we're not going
173 // to need it anymore from this point on (all hooks get forwarded to
174 // mEs->mResultHandler.
175 UniquePtr
<txResultBuffer
> buffer(std::move(mBuffer
));
176 return buffer
->flushToHandler(mEs
->mResultHandler
);