Chromium Code Reviews| Index: Source/core/loader/DocumentLoader.cpp |
| diff --git a/Source/core/loader/DocumentLoader.cpp b/Source/core/loader/DocumentLoader.cpp |
| index 650451786d46ccf01302669a1a1c1f74006602b8..c6c6802497fc5e77a687f82d1cd6fc750bc557d2 100644 |
| --- a/Source/core/loader/DocumentLoader.cpp |
| +++ b/Source/core/loader/DocumentLoader.cpp |
| @@ -30,13 +30,7 @@ |
| #include "config.h" |
| #include "core/loader/DocumentLoader.h" |
| -#include <wtf/Assertions.h> |
| -#include <wtf/MemoryInstrumentationHashMap.h> |
| -#include <wtf/MemoryInstrumentationHashSet.h> |
| -#include <wtf/MemoryInstrumentationVector.h> |
| -#include <wtf/text/CString.h> |
| -#include <wtf/text/WTFString.h> |
| -#include <wtf/unicode/Unicode.h> |
| +#include "core/dom/DOMImplementation.h" |
| #include "core/dom/Document.h" |
| #include "core/dom/DocumentParser.h" |
| #include "core/dom/Event.h" |
| @@ -50,6 +44,7 @@ |
| #include "core/loader/FrameLoader.h" |
| #include "core/loader/FrameLoaderClient.h" |
| #include "core/loader/ResourceLoader.h" |
| +#include "core/loader/SinkDocument.h" |
| #include "core/loader/TextResourceDecoder.h" |
| #include "core/loader/UniqueIdentifier.h" |
| #include "core/loader/appcache/ApplicationCacheHost.h" |
| @@ -66,6 +61,13 @@ |
| #include "core/platform/Logging.h" |
| #include "weborigin/SchemeRegistry.h" |
| #include "weborigin/SecurityPolicy.h" |
| +#include "wtf/Assertions.h" |
| +#include "wtf/MemoryInstrumentationHashMap.h" |
| +#include "wtf/MemoryInstrumentationHashSet.h" |
| +#include "wtf/MemoryInstrumentationVector.h" |
| +#include "wtf/text/CString.h" |
| +#include "wtf/text/WTFString.h" |
| +#include "wtf/unicode/Unicode.h" |
| namespace WebCore { |
| @@ -96,14 +98,12 @@ DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData& |
| : m_deferMainResourceDataLoad(true) |
| , m_frame(0) |
| , m_cachedResourceLoader(CachedResourceLoader::create(this)) |
| - , m_writer(m_frame) |
| , m_originalRequest(req) |
| , m_substituteData(substituteData) |
| , m_originalRequestCopy(req) |
| , m_request(req) |
| , m_committed(false) |
| , m_isStopping(false) |
| - , m_gotFirstByte(false) |
| , m_isClientRedirect(false) |
| , m_wasOnloadHandled(false) |
| , m_loadingMainResource(false) |
| @@ -298,7 +298,6 @@ void DocumentLoader::commitIfReady() |
| if (!m_committed) { |
| m_committed = true; |
| frameLoader()->commitProvisionalLoad(); |
| - m_writer.setMIMEType(m_response.mimeType()); |
| } |
| } |
| @@ -344,15 +343,19 @@ void DocumentLoader::finishedLoading(double finishTime) |
| if (!frameLoader()) |
| return; |
| - if (!maybeCreateArchive()) { |
| + if (isArchiveMIMEType(m_response.mimeType())) { |
| + createArchive(); |
| + } else { |
| // If this is an empty document, it will not have actually been created yet. Commit dummy data so that |
| // DocumentWriter::begin() gets called and creates the Document. |
| - if (!m_gotFirstByte) |
| + if (!m_writer) |
| commitData(0, 0); |
| + |
| frameLoader()->client()->finishedLoading(this); |
| } |
| - m_writer.end(); |
| + endWriting(m_writer.get()); |
| + |
| if (!m_mainDocumentError.isNull()) |
| return; |
| clearMainResourceLoader(); |
| @@ -629,34 +632,33 @@ void DocumentLoader::stopLoadingForPolicyChange() |
| cancelMainResourceLoad(error); |
| } |
| -void DocumentLoader::commitData(const char* bytes, size_t length) |
| +void DocumentLoader::ensureWriter() |
| { |
| - if (!m_gotFirstByte) { |
| - m_gotFirstByte = true; |
| - m_writer.begin(documentURL(), false); |
| - m_writer.setDocumentWasLoadedAsPartOfNavigation(); |
| + ensureWriter(m_response.mimeType()); |
| +} |
| - if (frameLoader()->stateMachine()->creatingInitialEmptyDocument()) |
| - return; |
| +void DocumentLoader::ensureWriter(const String& mimeType) |
| +{ |
| + if (m_writer) |
| + return; |
|
abarth-chromium
2013/06/26 03:04:08
Should we ASSERT that the mimeTypes match?
Hajime Morrita
2013/06/26 04:24:39
We should. Will do.
|
| + |
| + String encoding = overrideEncoding().isNull() ? response().textEncodingName().impl() : overrideEncoding(); |
| + bool userChosen = !overrideEncoding().isNull(); |
| + m_writer = createWriterFor(m_frame, 0, documentURL(), mimeType, encoding, false, true); |
| + m_writer->setDocumentWasLoadedAsPartOfNavigation(); |
| + |
| + if (frameLoader()->stateMachine()->creatingInitialEmptyDocument()) |
| + return; |
| - // The origin is the MHTML file, we need to set the base URL to the document encoded in the MHTML so |
| - // relative URLs are resolved properly. |
| - if (m_archive) |
| - m_frame->document()->setBaseURLOverride(m_archive->mainResource()->url()); |
| - |
| - // Call receivedFirstData() exactly once per load. |
| - frameLoader()->receivedFirstData(); |
| - |
| - bool userChosen = true; |
| - String encoding = overrideEncoding(); |
| - if (encoding.isNull()) { |
| - userChosen = false; |
| - encoding = response().textEncodingName(); |
| - } |
| - m_writer.setEncoding(encoding, userChosen); |
| - } |
| + // Call receivedFirstData() exactly once per load. |
| + frameLoader()->receivedFirstData(); |
| +} |
| + |
| +void DocumentLoader::commitData(const char* bytes, size_t length) |
| +{ |
| + ensureWriter(); |
| ASSERT(m_frame->document()->parsing()); |
| - m_writer.addData(bytes, length); |
| + m_writer->addData(bytes, length); |
| } |
| void DocumentLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
| @@ -711,8 +713,8 @@ void DocumentLoader::setFrame(Frame* frame) |
| if (m_frame == frame) |
| return; |
| ASSERT(frame && !m_frame); |
| + ASSERT(!m_writer); |
| m_frame = frame; |
| - m_writer.setFrame(frame); |
| } |
| void DocumentLoader::detachFromFrame() |
| @@ -763,22 +765,21 @@ bool DocumentLoader::isLoadingInAPISense() const |
| return frameLoader()->subframeIsLoading(); |
| } |
| -bool DocumentLoader::maybeCreateArchive() |
| +void DocumentLoader::createArchive() |
| { |
| - // Give the archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0. |
| - if (!isArchiveMIMEType(m_response.mimeType())) |
| - return false; |
| - |
| m_archive = MHTMLArchive::create(m_response.url(), mainResourceData().get()); |
| ASSERT(m_archive); |
| addAllArchiveResources(m_archive.get()); |
| ArchiveResource* mainResource = m_archive->mainResource(); |
| - m_writer.setMIMEType(mainResource->mimeType()); |
| - |
| - ASSERT(m_frame->document()); |
| + |
| + ensureWriter(mainResource->mimeType()); |
| + |
| + // The origin is the MHTML file, we need to set the base URL to the document encoded in the MHTML so |
| + // relative URLs are resolved properly. |
| + m_frame->document()->setBaseURLOverride(m_archive->mainResource()->url()); |
| + |
| commitData(mainResource->data()->data(), mainResource->data()->size()); |
| - return true; |
| } |
| void DocumentLoader::addAllArchiveResources(MHTMLArchive* archive) |
| @@ -901,9 +902,9 @@ void DocumentLoader::addResourceLoader(ResourceLoader* loader) |
| // The main resource's underlying ResourceLoader will ask to be added here. |
| // It is much simpler to handle special casing of main resource loads if we don't |
| // let it be added. In the main resource load case, mainResourceLoader() |
| - // will still be null at this point, but m_gotFirstByte should be false here if and only |
| + // will still be null at this point, but document() should be null here if and only |
|
abarth-chromium
2013/06/26 03:04:08
null -> zero
Hajime Morrita
2013/06/26 04:24:39
Done.
|
| // if we are just starting the main resource load. |
| - if (!m_gotFirstByte) |
| + if (!document()) |
| return; |
| ASSERT(!m_resourceLoaders.contains(loader)); |
| ASSERT(!mainResourceLoader() || mainResourceLoader() != loader); |
| @@ -1019,20 +1020,68 @@ void DocumentLoader::handledOnloadEvents() |
| DocumentWriter* DocumentLoader::beginWriting(const String& mimeType, const String& encoding, const KURL& url) |
| { |
| - m_writer.setMIMEType(mimeType); |
| - m_writer.setEncoding(encoding, false); |
| - m_writer.begin(url); |
| - return &m_writer; |
| + m_writer = createWriterFor(m_frame, 0, url, mimeType, encoding, false, true); |
| + return m_writer.get(); |
| +} |
| + |
| +void DocumentLoader::endWriting(DocumentWriter* writer) |
| +{ |
| + ASSERT_UNUSED(writer, m_writer == writer); |
| + m_writer->end(); |
| + m_writer.clear(); |
| +} |
| + |
| + |
| +PassOwnPtr<DocumentWriter> DocumentLoader::createWriterFor(Frame* frame, const Document* ownerDocument, const KURL& url, const String& mimeType, const String& encoding, bool userChosen, bool dispatch) |
| +{ |
| + // Create a new document before clearing the frame, because it may need to |
| + // inherit an aliased security context. |
| + RefPtr<Document> document = DOMImplementation::createDocument(mimeType, frame, url, frame->inViewSourceMode()); |
| + if (document->isPluginDocument() && document->isSandboxed(SandboxPlugins)) |
| + document = SinkDocument::create(frame, url); |
| + bool shouldReuseDefaultView = frame->loader()->stateMachine()->isDisplayingInitialEmptyDocument() && frame->document()->isSecureTransitionTo(url); |
| + |
| + RefPtr<DOMWindow> originalDOMWindow; |
| + if (shouldReuseDefaultView) |
| + originalDOMWindow = frame->domWindow(); |
| + frame->loader()->clear(!shouldReuseDefaultView, !shouldReuseDefaultView); |
| + |
| + if (!shouldReuseDefaultView) { |
| + frame->setDOMWindow(DOMWindow::create(frame)); |
| + } else { |
| + // Note that the old Document is still attached to the DOMWindow; the |
| + // setDocument() call below will detach the old Document. |
| + ASSERT(originalDOMWindow); |
| + frame->setDOMWindow(originalDOMWindow); |
| + } |
| + |
| + frame->loader()->setOutgoingReferrer(url); |
| + frame->domWindow()->setDocument(document); |
| + |
| + if (ownerDocument) { |
| + document->setCookieURL(ownerDocument->cookieURL()); |
| + document->setSecurityOrigin(ownerDocument->securityOrigin()); |
| + } |
| + |
| + frame->loader()->didBeginDocument(dispatch); |
| + |
| + return DocumentWriter::create(document.get(), mimeType, encoding, userChosen); |
| } |
| String DocumentLoader::mimeType() const |
| { |
| - return m_writer.mimeType(); |
| + return m_writer ? m_writer->mimeType() : m_response.mimeType().impl(); |
|
abarth-chromium
2013/06/26 03:04:08
impl() ?
Hajime Morrita
2013/06/26 04:24:39
I shouldn't have used the ternary operator :-|
|
| } |
| +// This is only called by ScriptController::executeScriptIfJavaScriptURL |
| +// and always contains the result of evaluating a javascript: url. |
| +// This is the <iframe src="javascript:'html'"> case. |
| void DocumentLoader::replaceDocument(const String& source, Document* ownerDocument) |
| { |
| - m_writer.replaceDocument(source, ownerDocument); |
| + m_writer = createWriterFor(m_frame, ownerDocument, m_frame->document()->url(), "", "", false, true); |
| + if (!source.isNull()) |
| + m_writer->appendReplacingData(source); |
| + endWriting(m_writer.get()); |
| } |
| } // namespace WebCore |