OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010. Adam Barth. All rights reserved. | 2 * Copyright (C) 2010. Adam Barth. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 11 matching lines...) Expand all Loading... |
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | 28 |
29 #include "config.h" | 29 #include "config.h" |
30 #include "core/loader/DocumentWriter.h" | 30 #include "core/loader/DocumentWriter.h" |
31 | 31 |
32 #include "core/dom/DOMImplementation.h" | 32 #include "core/dom/Document.h" |
33 #include "core/dom/ScriptableDocumentParser.h" | 33 #include "core/dom/ScriptableDocumentParser.h" |
34 #include "core/loader/FrameLoader.h" | 34 #include "core/loader/FrameLoader.h" |
35 #include "core/loader/FrameLoaderStateMachine.h" | 35 #include "core/loader/FrameLoaderStateMachine.h" |
36 #include "core/loader/SinkDocument.h" | |
37 #include "core/loader/TextResourceDecoder.h" | 36 #include "core/loader/TextResourceDecoder.h" |
38 #include "core/page/DOMWindow.h" | 37 #include "core/page/DOMWindow.h" |
39 #include "core/page/Frame.h" | 38 #include "core/page/Frame.h" |
40 #include "core/page/FrameView.h" | 39 #include "core/page/FrameView.h" |
41 #include "core/page/Settings.h" | 40 #include "core/page/Settings.h" |
42 #include "weborigin/KURL.h" | 41 #include "weborigin/KURL.h" |
43 #include "weborigin/SecurityOrigin.h" | 42 #include "weborigin/SecurityOrigin.h" |
| 43 #include "wtf/PassOwnPtr.h" |
44 | 44 |
45 namespace WebCore { | 45 namespace WebCore { |
46 | 46 |
47 DocumentWriter::DocumentWriter(Frame* frame) | 47 PassRefPtr<DocumentWriter> DocumentWriter::create(Document* document, const Stri
ng& mimeType, const String& encoding, bool encodingUserChoosen) |
48 : m_frame(frame) | 48 { |
| 49 return adoptRef(new DocumentWriter(document, mimeType, encoding, encodingUse
rChoosen)); |
| 50 } |
| 51 |
| 52 DocumentWriter::DocumentWriter(Document* document, const String& mimeType, const
String& encoding, bool encodingUserChoosen) |
| 53 : m_document(document) |
49 , m_hasReceivedSomeData(false) | 54 , m_hasReceivedSomeData(false) |
50 , m_state(NotStartedWritingState) | 55 , m_decoderBuilder(mimeType, encoding, encodingUserChoosen) |
| 56 // We grab a reference to the parser so that we'll always send data to the |
| 57 // original parser, even if the document acquires a new parser (e.g., via |
| 58 // document.open). |
| 59 , m_parser(m_document->implicitOpen()) |
| 60 { |
| 61 if (FrameView* view = m_document->frame()->view()) |
| 62 view->setContentsSize(IntSize()); |
| 63 } |
| 64 |
| 65 DocumentWriter::~DocumentWriter() |
51 { | 66 { |
52 } | 67 } |
53 | 68 |
54 // This is only called by ScriptController::executeScriptIfJavaScriptURL | 69 void DocumentWriter::appendReplacingData(const String& source) |
55 // and always contains the result of evaluating a javascript: url. | |
56 // This is the <iframe src="javascript:'html'"> case. | |
57 void DocumentWriter::replaceDocument(const String& source, Document* ownerDocume
nt) | |
58 { | 70 { |
59 m_frame->loader()->stopAllLoaders(); | 71 ASSERT(!m_hasReceivedSomeData); |
60 begin(m_frame->document()->url(), true, ownerDocument); | 72 m_hasReceivedSomeData = true; |
| 73 m_document->setCompatibilityMode(Document::NoQuirksMode); |
61 | 74 |
62 if (!source.isNull()) { | 75 // FIXME: This should call DocumentParser::appendBytes instead of append |
63 if (!m_hasReceivedSomeData) { | 76 // to support RawDataDocumentParsers. |
64 m_hasReceivedSomeData = true; | 77 if (DocumentParser* parser = m_document->parser()) { |
65 m_frame->document()->setCompatibilityMode(Document::NoQuirksMode); | 78 parser->pinToMainThread(); |
66 } | 79 // Because we're pinned to the main thread we don't need to worry about |
67 | 80 // passing ownership of the source string. |
68 // FIXME: This should call DocumentParser::appendBytes instead of append | 81 parser->append(source.impl()); |
69 // to support RawDataDocumentParsers. | |
70 if (DocumentParser* parser = m_frame->document()->parser()) { | |
71 parser->pinToMainThread(); | |
72 // Because we're pinned to the main thread we don't need to worry ab
out | |
73 // passing ownership of the source string. | |
74 parser->append(source.impl()); | |
75 } | |
76 } | 82 } |
77 | |
78 end(); | |
79 } | |
80 | |
81 void DocumentWriter::clear() | |
82 { | |
83 m_decoder = 0; | |
84 m_decoderBuilder.clear(); | |
85 m_hasReceivedSomeData = false; | |
86 } | |
87 | |
88 void DocumentWriter::begin() | |
89 { | |
90 begin(KURL()); | |
91 } | |
92 | |
93 PassRefPtr<Document> DocumentWriter::createDocument(const KURL& url) | |
94 { | |
95 return DOMImplementation::createDocument(mimeType(), m_frame, url, m_frame->
inViewSourceMode()); | |
96 } | |
97 | |
98 void DocumentWriter::begin(const KURL& urlReference, bool dispatch, Document* ow
nerDocument) | |
99 { | |
100 // We grab a local copy of the URL because it's easy for callers to supply | |
101 // a URL that will be deallocated during the execution of this function. | |
102 // For example, see <https://bugs.webkit.org/show_bug.cgi?id=66360>. | |
103 KURL url = urlReference; | |
104 | |
105 // Create a new document before clearing the frame, because it may need to | |
106 // inherit an aliased security context. | |
107 RefPtr<Document> document = createDocument(url); | |
108 | |
109 // If the new document is for a Plugin but we're supposed to be sandboxed fr
om Plugins, | |
110 // then replace the document with one whose parser will ignore the incoming
data (bug 39323) | |
111 if (document->isPluginDocument() && document->isSandboxed(SandboxPlugins)) | |
112 document = SinkDocument::create(m_frame, url); | |
113 | |
114 // FIXME: Do we need to consult the content security policy here about block
ed plug-ins? | |
115 | |
116 bool shouldReuseDefaultView = m_frame->loader()->stateMachine()->isDisplayin
gInitialEmptyDocument() && m_frame->document()->isSecureTransitionTo(url); | |
117 | |
118 RefPtr<DOMWindow> originalDOMWindow; | |
119 if (shouldReuseDefaultView) | |
120 originalDOMWindow = m_frame->domWindow(); | |
121 m_frame->loader()->clear(!shouldReuseDefaultView, !shouldReuseDefaultView); | |
122 clear(); | |
123 | |
124 if (!shouldReuseDefaultView) | |
125 m_frame->setDOMWindow(DOMWindow::create(m_frame)); | |
126 else { | |
127 // Note that the old Document is still attached to the DOMWindow; the | |
128 // setDocument() call below will detach the old Document. | |
129 ASSERT(originalDOMWindow); | |
130 m_frame->setDOMWindow(originalDOMWindow); | |
131 } | |
132 | |
133 m_frame->loader()->setOutgoingReferrer(url); | |
134 m_frame->domWindow()->setDocument(document); | |
135 | |
136 if (m_decoder) | |
137 document->setDecoder(m_decoder.get()); | |
138 if (ownerDocument) { | |
139 document->setCookieURL(ownerDocument->cookieURL()); | |
140 document->setSecurityOrigin(ownerDocument->securityOrigin()); | |
141 } | |
142 | |
143 m_frame->loader()->didBeginDocument(dispatch); | |
144 | |
145 document->implicitOpen(); | |
146 | |
147 // We grab a reference to the parser so that we'll always send data to the | |
148 // original parser, even if the document acquires a new parser (e.g., via | |
149 // document.open). | |
150 m_parser = document->parser(); | |
151 | |
152 if (m_frame->view()) | |
153 m_frame->view()->setContentsSize(IntSize()); | |
154 | |
155 m_state = StartedWritingState; | |
156 } | 83 } |
157 | 84 |
158 void DocumentWriter::reportDataReceived() | 85 void DocumentWriter::reportDataReceived() |
159 { | 86 { |
160 ASSERT(m_decoder); | 87 ASSERT(m_decoder); |
161 if (m_hasReceivedSomeData) | 88 if (m_hasReceivedSomeData) |
162 return; | 89 return; |
163 m_hasReceivedSomeData = true; | 90 m_hasReceivedSomeData = true; |
164 if (m_decoder->encoding().usesVisualOrdering()) | 91 if (m_decoder->encoding().usesVisualOrdering()) |
165 m_frame->document()->setVisuallyOrdered(); | 92 m_document->setVisuallyOrdered(); |
166 } | 93 } |
167 | 94 |
168 void DocumentWriter::addData(const char* bytes, size_t length) | 95 void DocumentWriter::addData(const char* bytes, size_t length) |
169 { | 96 { |
170 // Check that we're inside begin()/end(). | |
171 // FIXME: Change these to ASSERT once https://bugs.webkit.org/show_bug.cgi?i
d=80427 has | |
172 // been resolved. | |
173 if (m_state == NotStartedWritingState) | |
174 CRASH(); | |
175 if (m_state == FinishedWritingState) | |
176 CRASH(); | |
177 | |
178 ASSERT(m_parser); | 97 ASSERT(m_parser); |
179 if (!m_decoder && m_parser->needsDecoder() && 0 < length) | 98 if (!m_decoder && m_parser->needsDecoder() && 0 < length) |
180 m_decoder = m_decoderBuilder.buildFor(m_frame->document()); | 99 m_decoder = m_decoderBuilder.buildFor(m_document); |
| 100 // appendBytes() can result replacing DocumentLoader::m_writer. |
| 101 RefPtr<DocumentWriter> protectingThis(this); |
181 size_t consumedChars = m_parser->appendBytes(bytes, length); | 102 size_t consumedChars = m_parser->appendBytes(bytes, length); |
182 if (consumedChars) | 103 if (consumedChars) |
183 reportDataReceived(); | 104 reportDataReceived(); |
184 } | 105 } |
185 | 106 |
186 void DocumentWriter::end() | 107 void DocumentWriter::end() |
187 { | 108 { |
188 ASSERT(m_frame->page()); | 109 ASSERT(m_document); |
189 ASSERT(m_frame->document()); | |
190 | |
191 // The parser is guaranteed to be released after this point. begin() would | |
192 // have to be called again before we can start writing more data. | |
193 m_state = FinishedWritingState; | |
194 | 110 |
195 // http://bugs.webkit.org/show_bug.cgi?id=10854 | 111 // http://bugs.webkit.org/show_bug.cgi?id=10854 |
196 // The frame's last ref may be removed and it can be deleted by checkComplet
ed(), | 112 // The frame's last ref may be removed and it can be deleted by checkComplet
ed(), |
197 // so we'll add a protective refcount | 113 // so we'll add a protective refcount |
198 RefPtr<Frame> protector(m_frame); | 114 RefPtr<Frame> protector(m_document->frame()); |
199 | 115 |
200 if (!m_parser) | 116 if (!m_parser) |
201 return; | 117 return; |
| 118 |
202 if (!m_decoder && m_parser->needsDecoder()) | 119 if (!m_decoder && m_parser->needsDecoder()) |
203 m_decoder = m_decoderBuilder.buildFor(m_frame->document()); | 120 m_decoder = m_decoderBuilder.buildFor(m_document); |
| 121 // flush() can result replacing DocumentLoader::m_writer. |
| 122 RefPtr<DocumentWriter> protectingThis(this); |
204 size_t consumedChars = m_parser->flush(); | 123 size_t consumedChars = m_parser->flush(); |
205 if (consumedChars) | 124 if (consumedChars) |
206 reportDataReceived(); | 125 reportDataReceived(); |
207 if (!m_parser) | 126 if (!m_parser) |
208 return; | 127 return; |
| 128 |
209 m_parser->finish(); | 129 m_parser->finish(); |
210 m_parser = 0; | 130 m_parser = 0; |
| 131 m_document = 0; |
211 } | 132 } |
212 | 133 |
213 void DocumentWriter::setDocumentWasLoadedAsPartOfNavigation() | 134 void DocumentWriter::setDocumentWasLoadedAsPartOfNavigation() |
214 { | 135 { |
215 ASSERT(m_parser && !m_parser->isStopped()); | 136 ASSERT(m_parser && !m_parser->isStopped()); |
216 m_parser->setDocumentWasLoadedAsPartOfNavigation(); | 137 m_parser->setDocumentWasLoadedAsPartOfNavigation(); |
217 } | 138 } |
218 | 139 |
219 } // namespace WebCore | 140 } // namespace WebCore |
OLD | NEW |