1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "nsHtml5StringParser.h"
6 #include "nsHtml5DependentUTF16Buffer.h"
7 #include "nsHtml5Tokenizer.h"
8 #include "nsHtml5TreeBuilder.h"
9 #include "nsHtml5TreeOpExecutor.h"
10 #include "nsIContent.h"
11 #include "mozilla/dom/Document.h"
12 #include "mozilla/dom/DocumentFragment.h"
13
14 using mozilla::dom::Document;
15
NS_IMPL_ISUPPORTS0(nsHtml5StringParser)16 NS_IMPL_ISUPPORTS0(nsHtml5StringParser)
17
18 nsHtml5StringParser::nsHtml5StringParser()
19 : mBuilder(new nsHtml5OplessBuilder()),
20 mTreeBuilder(new nsHtml5TreeBuilder(mBuilder)),
21 mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)) {
22 mTokenizer->setInterner(&mAtomTable);
23 }
24
~nsHtml5StringParser()25 nsHtml5StringParser::~nsHtml5StringParser() {}
26
ParseFragment(const nsAString & aSourceBuffer,nsIContent * aTargetNode,nsAtom * aContextLocalName,int32_t aContextNamespace,bool aQuirks,bool aPreventScriptExecution)27 nsresult nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer,
28 nsIContent* aTargetNode,
29 nsAtom* aContextLocalName,
30 int32_t aContextNamespace,
31 bool aQuirks,
32 bool aPreventScriptExecution) {
33 NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
34
35 Document* doc = aTargetNode->OwnerDoc();
36 nsIURI* uri = doc->GetDocumentURI();
37 NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
38
39 mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace,
40 aTargetNode, aQuirks);
41
42 #ifdef DEBUG
43 if (!aPreventScriptExecution) {
44 NS_ASSERTION(!aTargetNode->IsInUncomposedDoc(),
45 "If script execution isn't prevented, "
46 "the target node must not be in doc.");
47 NS_ASSERTION(
48 aTargetNode->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE,
49 "If script execution isn't prevented, must parse to DOM fragment.");
50 }
51 #endif
52
53 mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution);
54
55 return Tokenize(aSourceBuffer, doc, true);
56 }
57
ParseDocument(const nsAString & aSourceBuffer,Document * aTargetDoc,bool aScriptingEnabledForNoscriptParsing)58 nsresult nsHtml5StringParser::ParseDocument(
59 const nsAString& aSourceBuffer, Document* aTargetDoc,
60 bool aScriptingEnabledForNoscriptParsing) {
61 MOZ_ASSERT(!aTargetDoc->GetFirstChild());
62
63 NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
64
65 mTreeBuilder->setFragmentContext(nullptr, kNameSpaceID_None, nullptr, false);
66
67 mTreeBuilder->SetPreventScriptExecution(true);
68
69 return Tokenize(aSourceBuffer, aTargetDoc,
70 aScriptingEnabledForNoscriptParsing);
71 }
72
Tokenize(const nsAString & aSourceBuffer,Document * aDocument,bool aScriptingEnabledForNoscriptParsing)73 nsresult nsHtml5StringParser::Tokenize(
74 const nsAString& aSourceBuffer, Document* aDocument,
75 bool aScriptingEnabledForNoscriptParsing) {
76 nsIURI* uri = aDocument->GetDocumentURI();
77
78 mBuilder->Init(aDocument, uri, nullptr, nullptr);
79
80 mBuilder->SetParser(this);
81 mBuilder->SetNodeInfoManager(aDocument->NodeInfoManager());
82
83 // Mark the parser as *not* broken by passing NS_OK
84 nsresult rv = mBuilder->MarkAsBroken(NS_OK);
85
86 mTreeBuilder->setScriptingEnabled(aScriptingEnabledForNoscriptParsing);
87 mTreeBuilder->setIsSrcdocDocument(aDocument->IsSrcdocDocument());
88 mBuilder->Start();
89 mTokenizer->start();
90 if (!aSourceBuffer.IsEmpty()) {
91 bool lastWasCR = false;
92 nsHtml5DependentUTF16Buffer buffer(aSourceBuffer);
93 while (buffer.hasMore()) {
94 buffer.adjust(lastWasCR);
95 lastWasCR = false;
96 if (buffer.hasMore()) {
97 if (!mTokenizer->EnsureBufferSpace(buffer.getLength())) {
98 rv = mBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
99 break;
100 }
101 lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
102 if (NS_FAILED(rv = mBuilder->IsBroken())) {
103 break;
104 }
105 }
106 }
107 }
108 if (NS_SUCCEEDED(rv)) {
109 mTokenizer->eof();
110 }
111 mTokenizer->end();
112 mBuilder->Finish();
113 mAtomTable.Clear();
114 return rv;
115 }
116