Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; 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/. */
5 #include "nsCOMPtr.h"
6 #include "nsXMLContentSink.h"
7 #include "nsIFragmentContentSink.h"
8 #include "nsIXMLContentSink.h"
9 #include "nsContentSink.h"
10 #include "nsIExpatSink.h"
11 #include "nsIDTD.h"
12 #include "nsIDocument.h"
13 #include "nsIDOMDocumentFragment.h"
14 #include "nsIContent.h"
15 #include "nsGkAtoms.h"
16 #include "nsINodeInfo.h"
17 #include "nsContentCreatorFunctions.h"
18 #include "nsError.h"
19 #include "nsIConsoleService.h"
20 #include "nsIScriptError.h"
21 #include "nsNetUtil.h"
22 #include "nsTHashtable.h"
23 #include "nsHashKeys.h"
24 #include "nsTArray.h"
25 #include "nsCycleCollectionParticipant.h"
26 #include "nsIDocShell.h"
27 #include "nsScriptLoader.h"
28 #include "mozilla/css/Loader.h"
29 #include "mozilla/dom/DocumentFragment.h"
30 #include "mozilla/dom/ProcessingInstruction.h"
32 using namespace mozilla::dom;
34 class nsXMLFragmentContentSink : public nsXMLContentSink,
35 public nsIFragmentContentSink
36 {
37 public:
38 nsXMLFragmentContentSink();
39 virtual ~nsXMLFragmentContentSink();
41 NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
43 // nsISupports
44 NS_DECL_ISUPPORTS_INHERITED
45 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLFragmentContentSink,
46 nsXMLContentSink)
48 // nsIExpatSink
49 NS_IMETHOD HandleDoctypeDecl(const nsAString & aSubset,
50 const nsAString & aName,
51 const nsAString & aSystemId,
52 const nsAString & aPublicId,
53 nsISupports* aCatalogData);
54 NS_IMETHOD HandleProcessingInstruction(const char16_t *aTarget,
55 const char16_t *aData);
56 NS_IMETHOD HandleXMLDeclaration(const char16_t *aVersion,
57 const char16_t *aEncoding,
58 int32_t aStandalone);
59 NS_IMETHOD ReportError(const char16_t* aErrorText,
60 const char16_t* aSourceText,
61 nsIScriptError *aError,
62 bool *_retval);
64 // nsIContentSink
65 NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode);
66 NS_IMETHOD DidBuildModel(bool aTerminated);
67 NS_IMETHOD SetDocumentCharset(nsACString& aCharset);
68 virtual nsISupports *GetTarget();
69 NS_IMETHOD DidProcessATokenImpl();
71 // nsIXMLContentSink
73 // nsIFragmentContentSink
74 NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment);
75 NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
76 NS_IMETHOD WillBuildContent();
77 NS_IMETHOD DidBuildContent();
78 NS_IMETHOD IgnoreFirstContainer();
79 NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution);
81 protected:
82 virtual bool SetDocElement(int32_t aNameSpaceID,
83 nsIAtom *aTagName,
84 nsIContent *aContent);
85 virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
86 nsINodeInfo* aNodeInfo, uint32_t aLineNumber,
87 nsIContent** aResult, bool* aAppendContent,
88 mozilla::dom::FromParser aFromParser);
89 virtual nsresult CloseElement(nsIContent* aContent);
91 virtual void MaybeStartLayout(bool aIgnorePendingSheets);
93 // nsContentSink overrides
94 virtual nsresult ProcessStyleLink(nsIContent* aElement,
95 const nsSubstring& aHref,
96 bool aAlternate,
97 const nsSubstring& aTitle,
98 const nsSubstring& aType,
99 const nsSubstring& aMedia);
100 nsresult LoadXSLStyleSheet(nsIURI* aUrl);
101 void StartLayout();
103 nsCOMPtr<nsIDocument> mTargetDocument;
104 // the fragment
105 nsCOMPtr<nsIContent> mRoot;
106 bool mParseError;
107 };
109 static nsresult
110 NewXMLFragmentContentSinkHelper(nsIFragmentContentSink** aResult)
111 {
112 nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink();
114 NS_ADDREF(*aResult = it);
116 return NS_OK;
117 }
119 nsresult
120 NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult)
121 {
122 return NewXMLFragmentContentSinkHelper(aResult);
123 }
125 nsXMLFragmentContentSink::nsXMLFragmentContentSink()
126 : mParseError(false)
127 {
128 mRunsToCompletion = true;
129 }
131 nsXMLFragmentContentSink::~nsXMLFragmentContentSink()
132 {
133 }
135 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink)
136 NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
137 NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink)
139 NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
140 NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
142 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLFragmentContentSink)
144 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLFragmentContentSink,
145 nsXMLContentSink)
146 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTargetDocument)
147 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
148 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
150 NS_IMETHODIMP
151 nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode)
152 {
153 if (mRoot) {
154 return NS_OK;
155 }
157 mState = eXMLContentSinkState_InDocumentElement;
159 NS_ASSERTION(mTargetDocument, "Need a document!");
161 mRoot = new DocumentFragment(mNodeInfoManager);
163 return NS_OK;
164 }
166 NS_IMETHODIMP
167 nsXMLFragmentContentSink::DidBuildModel(bool aTerminated)
168 {
169 nsRefPtr<nsParserBase> kungFuDeathGrip(mParser);
171 // Drop our reference to the parser to get rid of a circular
172 // reference.
173 mParser = nullptr;
175 return NS_OK;
176 }
178 NS_IMETHODIMP
179 nsXMLFragmentContentSink::SetDocumentCharset(nsACString& aCharset)
180 {
181 NS_NOTREACHED("fragments shouldn't set charset");
182 return NS_OK;
183 }
185 nsISupports *
186 nsXMLFragmentContentSink::GetTarget()
187 {
188 return mTargetDocument;
189 }
191 ////////////////////////////////////////////////////////////////////////
193 bool
194 nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID,
195 nsIAtom* aTagName,
196 nsIContent *aContent)
197 {
198 // this is a fragment, not a document
199 return false;
200 }
202 nsresult
203 nsXMLFragmentContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
204 nsINodeInfo* aNodeInfo, uint32_t aLineNumber,
205 nsIContent** aResult, bool* aAppendContent,
206 FromParser /*aFromParser*/)
207 {
208 // Claim to not be coming from parser, since we don't do any of the
209 // fancy CloseElement stuff.
210 nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount,
211 aNodeInfo, aLineNumber,
212 aResult, aAppendContent,
213 NOT_FROM_PARSER);
215 // When we aren't grabbing all of the content we, never open a doc
216 // element, we run into trouble on the first element, so we don't append,
217 // and simply push this onto the content stack.
218 if (mContentStack.Length() == 0) {
219 *aAppendContent = false;
220 }
222 return rv;
223 }
225 nsresult
226 nsXMLFragmentContentSink::CloseElement(nsIContent* aContent)
227 {
228 // don't do fancy stuff in nsXMLContentSink
229 if (mPreventScriptExecution && aContent->Tag() == nsGkAtoms::script &&
230 (aContent->IsHTML() || aContent->IsSVG())) {
231 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
232 NS_ASSERTION(sele, "script did QI correctly!");
233 sele->PreventExecution();
234 }
235 return NS_OK;
236 }
238 void
239 nsXMLFragmentContentSink::MaybeStartLayout(bool aIgnorePendingSheets)
240 {
241 return;
242 }
244 ////////////////////////////////////////////////////////////////////////
246 NS_IMETHODIMP
247 nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString & aSubset,
248 const nsAString & aName,
249 const nsAString & aSystemId,
250 const nsAString & aPublicId,
251 nsISupports* aCatalogData)
252 {
253 NS_NOTREACHED("fragments shouldn't have doctype declarations");
255 return NS_OK;
256 }
258 NS_IMETHODIMP
259 nsXMLFragmentContentSink::HandleProcessingInstruction(const char16_t *aTarget,
260 const char16_t *aData)
261 {
262 FlushText();
264 const nsDependentString target(aTarget);
265 const nsDependentString data(aData);
267 nsRefPtr<ProcessingInstruction> node =
268 NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data);
270 // no special processing here. that should happen when the fragment moves into the document
271 return AddContentAsLeaf(node);
272 }
274 NS_IMETHODIMP
275 nsXMLFragmentContentSink::HandleXMLDeclaration(const char16_t *aVersion,
276 const char16_t *aEncoding,
277 int32_t aStandalone)
278 {
279 NS_NOTREACHED("fragments shouldn't have XML declarations");
280 return NS_OK;
281 }
283 NS_IMETHODIMP
284 nsXMLFragmentContentSink::ReportError(const char16_t* aErrorText,
285 const char16_t* aSourceText,
286 nsIScriptError *aError,
287 bool *_retval)
288 {
289 NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
291 // The expat driver should report the error.
292 *_retval = true;
294 mParseError = true;
296 #ifdef DEBUG
297 // Report the error to stderr.
298 fprintf(stderr,
299 "\n%s\n%s\n\n",
300 NS_LossyConvertUTF16toASCII(aErrorText).get(),
301 NS_LossyConvertUTF16toASCII(aSourceText).get());
302 #endif
304 // The following code is similar to the cleanup in nsXMLContentSink::ReportError()
305 mState = eXMLContentSinkState_InProlog;
307 // Clear the current content
308 nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot));
309 if (node) {
310 for (;;) {
311 nsCOMPtr<nsIDOMNode> child, dummy;
312 node->GetLastChild(getter_AddRefs(child));
313 if (!child)
314 break;
315 node->RemoveChild(child, getter_AddRefs(dummy));
316 }
317 }
319 // Clear any buffered-up text we have. It's enough to set the length to 0.
320 // The buffer itself is allocated when we're created and deleted in our
321 // destructor, so don't mess with it.
322 mTextLength = 0;
324 return NS_OK;
325 }
327 nsresult
328 nsXMLFragmentContentSink::ProcessStyleLink(nsIContent* aElement,
329 const nsSubstring& aHref,
330 bool aAlternate,
331 const nsSubstring& aTitle,
332 const nsSubstring& aType,
333 const nsSubstring& aMedia)
334 {
335 // don't process until moved to document
336 return NS_OK;
337 }
339 nsresult
340 nsXMLFragmentContentSink::LoadXSLStyleSheet(nsIURI* aUrl)
341 {
342 NS_NOTREACHED("fragments shouldn't have XSL style sheets");
343 return NS_ERROR_UNEXPECTED;
344 }
346 void
347 nsXMLFragmentContentSink::StartLayout()
348 {
349 NS_NOTREACHED("fragments shouldn't layout");
350 }
352 ////////////////////////////////////////////////////////////////////////
354 NS_IMETHODIMP
355 nsXMLFragmentContentSink::FinishFragmentParsing(nsIDOMDocumentFragment** aFragment)
356 {
357 *aFragment = nullptr;
358 mTargetDocument = nullptr;
359 mNodeInfoManager = nullptr;
360 mScriptLoader = nullptr;
361 mCSSLoader = nullptr;
362 mContentStack.Clear();
363 mDocumentURI = nullptr;
364 mDocShell = nullptr;
365 mDocElement = nullptr;
366 mCurrentHead = nullptr;
367 if (mParseError) {
368 //XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
369 mRoot = nullptr;
370 mParseError = false;
371 return NS_ERROR_DOM_SYNTAX_ERR;
372 } else if (mRoot) {
373 nsresult rv = CallQueryInterface(mRoot, aFragment);
374 mRoot = nullptr;
375 return rv;
376 } else {
377 return NS_OK;
378 }
379 }
381 NS_IMETHODIMP
382 nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
383 {
384 NS_ENSURE_ARG_POINTER(aTargetDocument);
386 mTargetDocument = aTargetDocument;
387 mNodeInfoManager = aTargetDocument->NodeInfoManager();
389 return NS_OK;
390 }
392 NS_IMETHODIMP
393 nsXMLFragmentContentSink::WillBuildContent()
394 {
395 PushContent(mRoot);
397 return NS_OK;
398 }
400 NS_IMETHODIMP
401 nsXMLFragmentContentSink::DidBuildContent()
402 {
403 // Note: we need to FlushText() here because if we don't, we might not get
404 // an end element to do it for us, so make sure.
405 if (!mParseError) {
406 FlushText();
407 }
408 PopContent();
410 return NS_OK;
411 }
413 NS_IMETHODIMP
414 nsXMLFragmentContentSink::DidProcessATokenImpl()
415 {
416 return NS_OK;
417 }
419 NS_IMETHODIMP
420 nsXMLFragmentContentSink::IgnoreFirstContainer()
421 {
422 NS_NOTREACHED("XML isn't as broken as HTML");
423 return NS_ERROR_FAILURE;
424 }
426 NS_IMETHODIMP
427 nsXMLFragmentContentSink::SetPreventScriptExecution(bool aPrevent)
428 {
429 mPreventScriptExecution = aPrevent;
430 return NS_OK;
431 }