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