Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/. */
5 :
6 : #include "txUnknownHandler.h"
7 :
8 : #include "mozilla/Move.h"
9 : #include "txExecutionState.h"
10 : #include "txStringUtils.h"
11 : #include "txStylesheet.h"
12 : #include "nsGkAtoms.h"
13 :
14 : using mozilla::Move;
15 :
16 0 : txUnknownHandler::txUnknownHandler(txExecutionState* aEs)
17 : : mEs(aEs),
18 0 : mFlushed(false)
19 : {
20 0 : MOZ_COUNT_CTOR_INHERITED(txUnknownHandler, txBufferingHandler);
21 0 : }
22 :
23 0 : txUnknownHandler::~txUnknownHandler()
24 : {
25 0 : MOZ_COUNT_DTOR_INHERITED(txUnknownHandler, txBufferingHandler);
26 0 : }
27 :
28 : nsresult
29 0 : txUnknownHandler::attribute(nsIAtom* aPrefix, nsIAtom* aLocalName,
30 : nsIAtom* aLowercaseLocalName, int32_t aNsID,
31 : const nsString& aValue)
32 : {
33 0 : return mFlushed ?
34 0 : mEs->mResultHandler->attribute(aPrefix, aLocalName,
35 0 : aLowercaseLocalName, aNsID, aValue) :
36 0 : txBufferingHandler::attribute(aPrefix, aLocalName,
37 0 : aLowercaseLocalName, aNsID, aValue);
38 : }
39 :
40 : nsresult
41 0 : txUnknownHandler::attribute(nsIAtom* aPrefix, const nsAString& aLocalName,
42 : const int32_t aNsID, const nsString& aValue)
43 : {
44 0 : return mFlushed ?
45 0 : mEs->mResultHandler->attribute(aPrefix, aLocalName, aNsID, aValue) :
46 0 : txBufferingHandler::attribute(aPrefix, aLocalName, aNsID, aValue);
47 : }
48 :
49 : nsresult
50 0 : txUnknownHandler::characters(const nsAString& aData, bool aDOE)
51 : {
52 0 : return mFlushed ?
53 0 : mEs->mResultHandler->characters(aData, aDOE) :
54 0 : txBufferingHandler::characters(aData, aDOE);
55 : }
56 :
57 : nsresult
58 0 : txUnknownHandler::comment(const nsString& aData)
59 : {
60 0 : return mFlushed ?
61 0 : mEs->mResultHandler->comment(aData) :
62 0 : txBufferingHandler::comment(aData);
63 : }
64 :
65 : nsresult
66 0 : txUnknownHandler::endDocument(nsresult aResult)
67 : {
68 0 : if (!mFlushed) {
69 0 : if (NS_FAILED(aResult)) {
70 0 : return NS_OK;
71 : }
72 :
73 : // This is an unusual case, no output method has been set and we
74 : // didn't create a document element. Switching to XML output mode
75 : // anyway.
76 :
77 : // Make sure that mEs->mResultHandler == this is true, otherwise we'll
78 : // leak mEs->mResultHandler in createHandlerAndFlush.
79 0 : NS_ASSERTION(mEs->mResultHandler == this,
80 : "We're leaking mEs->mResultHandler.");
81 :
82 0 : nsresult rv = createHandlerAndFlush(false, EmptyString(),
83 0 : kNameSpaceID_None);
84 0 : NS_ENSURE_SUCCESS(rv, rv);
85 : }
86 :
87 0 : return mEs->mResultHandler->endDocument(aResult);
88 : }
89 :
90 : nsresult
91 0 : txUnknownHandler::endElement()
92 : {
93 0 : return mFlushed ?
94 0 : mEs->mResultHandler->endElement() :
95 0 : txBufferingHandler::endElement();
96 : }
97 :
98 : nsresult
99 0 : txUnknownHandler::processingInstruction(const nsString& aTarget,
100 : const nsString& aData)
101 : {
102 0 : return mFlushed ?
103 0 : mEs->mResultHandler->processingInstruction(aTarget, aData) :
104 0 : txBufferingHandler::processingInstruction(aTarget, aData);
105 : }
106 :
107 : nsresult
108 0 : txUnknownHandler::startDocument()
109 : {
110 0 : return mFlushed ?
111 0 : mEs->mResultHandler->startDocument() :
112 0 : txBufferingHandler::startDocument();
113 : }
114 :
115 : nsresult
116 0 : txUnknownHandler::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
117 : nsIAtom* aLowercaseLocalName, int32_t aNsID)
118 : {
119 0 : if (!mFlushed) {
120 : // Make sure that mEs->mResultHandler == this is true, otherwise we'll
121 : // leak mEs->mResultHandler in createHandlerAndFlush.
122 0 : NS_ASSERTION(mEs->mResultHandler == this,
123 : "We're leaking mEs->mResultHandler.");
124 :
125 0 : nsCOMPtr<nsIAtom> owner;
126 0 : if (!aLowercaseLocalName) {
127 0 : owner = TX_ToLowerCaseAtom(aLocalName);
128 0 : NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
129 :
130 0 : aLowercaseLocalName = owner;
131 : }
132 :
133 0 : bool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix &&
134 0 : aLowercaseLocalName == nsGkAtoms::html;
135 :
136 : // Use aLocalName and not aLowercaseLocalName in case the output
137 : // handler cares about case. For eHTMLOutput the handler will hardcode
138 : // to 'html' anyway.
139 0 : nsresult rv = createHandlerAndFlush(htmlRoot,
140 0 : nsDependentAtomString(aLocalName),
141 0 : aNsID);
142 0 : NS_ENSURE_SUCCESS(rv, rv);
143 : }
144 :
145 0 : return mEs->mResultHandler->startElement(aPrefix, aLocalName,
146 0 : aLowercaseLocalName, aNsID);
147 : }
148 :
149 : nsresult
150 0 : txUnknownHandler::startElement(nsIAtom* aPrefix, const nsAString& aLocalName,
151 : const int32_t aNsID)
152 : {
153 0 : if (!mFlushed) {
154 : // Make sure that mEs->mResultHandler == this is true, otherwise we'll
155 : // leak mEs->mResultHandler in createHandlerAndFlush.
156 0 : NS_ASSERTION(mEs->mResultHandler == this,
157 : "We're leaking mEs->mResultHandler.");
158 :
159 0 : bool htmlRoot = aNsID == kNameSpaceID_None && !aPrefix &&
160 0 : aLocalName.Equals(NS_LITERAL_STRING("html"),
161 0 : txCaseInsensitiveStringComparator());
162 0 : nsresult rv = createHandlerAndFlush(htmlRoot, aLocalName, aNsID);
163 0 : NS_ENSURE_SUCCESS(rv, rv);
164 : }
165 :
166 0 : return mEs->mResultHandler->startElement(aPrefix, aLocalName, aNsID);
167 : }
168 :
169 0 : nsresult txUnknownHandler::createHandlerAndFlush(bool aHTMLRoot,
170 : const nsAString& aName,
171 : const int32_t aNsID)
172 : {
173 0 : NS_ENSURE_TRUE(mBuffer, NS_ERROR_NOT_INITIALIZED);
174 :
175 0 : txOutputFormat format;
176 0 : format.merge(*(mEs->mStylesheet->getOutputFormat()));
177 0 : if (format.mMethod == eMethodNotSet) {
178 0 : format.mMethod = aHTMLRoot ? eHTMLOutput : eXMLOutput;
179 : }
180 :
181 0 : nsAutoPtr<txAXMLEventHandler> handler;
182 0 : nsresult rv = mEs->mOutputHandlerFactory->createHandlerWith(&format, aName,
183 : aNsID,
184 0 : getter_Transfers(handler));
185 0 : NS_ENSURE_SUCCESS(rv, rv);
186 :
187 0 : mEs->mOutputHandler = handler;
188 0 : mEs->mResultHandler = handler.forget();
189 : // Let the executionstate delete us. We need to stay alive because we might
190 : // need to forward hooks to mEs->mResultHandler if someone is currently
191 : // flushing a buffer to mEs->mResultHandler.
192 0 : mEs->mObsoleteHandler = this;
193 :
194 0 : mFlushed = true;
195 :
196 : // Let go of out buffer as soon as we're done flushing it, we're not going
197 : // to need it anymore from this point on (all hooks get forwarded to
198 : // mEs->mResultHandler.
199 0 : nsAutoPtr<txResultBuffer> buffer(Move(mBuffer));
200 0 : return buffer->flushToHandler(mEs->mResultHandler);
201 : }
|