| Index: Source/core/loader/DocumentLoader.cpp
|
| diff --git a/Source/core/loader/DocumentLoader.cpp b/Source/core/loader/DocumentLoader.cpp
|
| index cf17c906e4b9929a046b7bf64d569aeb45a2adb0..b878158248a717d8d5535fc453b2807db5f55db2 100644
|
| --- a/Source/core/loader/DocumentLoader.cpp
|
| +++ b/Source/core/loader/DocumentLoader.cpp
|
| @@ -30,6 +30,7 @@
|
| #include "config.h"
|
| #include "core/loader/DocumentLoader.h"
|
|
|
| +#include "core/dom/DOMImplementation.h"
|
| #include "core/dom/Document.h"
|
| #include "core/dom/DocumentParser.h"
|
| #include "core/dom/Event.h"
|
| @@ -40,6 +41,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"
|
| @@ -53,7 +55,9 @@
|
| #include "core/page/FrameTree.h"
|
| #include "core/page/Page.h"
|
| #include "core/page/Settings.h"
|
| +#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"
|
| @@ -89,14 +93,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)
|
| @@ -290,7 +292,6 @@ void DocumentLoader::commitIfReady()
|
| if (!m_committed) {
|
| m_committed = true;
|
| frameLoader()->commitProvisionalLoad();
|
| - m_writer.setMIMEType(m_response.mimeType());
|
| }
|
| }
|
|
|
| @@ -336,14 +337,17 @@ 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);
|
| }
|
|
|
| - m_writer.end();
|
| + endWriting(m_writer.get());
|
| +
|
| if (!m_mainDocumentError.isNull())
|
| return;
|
| clearMainResourceLoader();
|
| @@ -604,34 +608,37 @@ 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;
|
| -
|
| - // 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);
|
| - }
|
| +void DocumentLoader::ensureWriter(const String& mimeType, const KURL& overridingURL)
|
| +{
|
| + if (m_writer)
|
| + return;
|
| +
|
| + String encoding = overrideEncoding().isNull() ? response().textEncodingName().impl() : overrideEncoding();
|
| + bool userChosen = !overrideEncoding().isNull();
|
| + m_writer = createWriterFor(m_frame, 0, documentURL(), mimeType, encoding, false, false);
|
| + m_writer->setDocumentWasLoadedAsPartOfNavigation();
|
| +
|
| + if (frameLoader()->stateMachine()->creatingInitialEmptyDocument())
|
| + return;
|
| +
|
| + // This should be set before receivedFirstData().
|
| + if (!overridingURL.isEmpty())
|
| + m_frame->document()->setBaseURLOverride(overridingURL);
|
| +
|
| + // 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
|
| @@ -702,8 +709,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()
|
| @@ -754,22 +761,19 @@ 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());
|
| +
|
| + // 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.
|
| + ensureWriter(mainResource->mimeType(), m_archive->mainResource()->url());
|
| +
|
| commitData(mainResource->data()->data(), mainResource->data()->size());
|
| - return true;
|
| }
|
|
|
| void DocumentLoader::addAllArchiveResources(MHTMLArchive* archive)
|
| @@ -892,9 +896,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 zero here if and only
|
| // if we are just starting the main resource load.
|
| - if (!m_gotFirstByte)
|
| + if (!document())
|
| return;
|
| ASSERT(!m_resourceLoaders.contains(loader));
|
| ASSERT(!mainResourceLoader() || mainResourceLoader() != loader);
|
| @@ -1010,20 +1014,71 @@ 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();
|
| +}
|
| +
|
| +
|
| +PassRefPtr<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();
|
| + if (m_writer)
|
| + return m_writer->mimeType();
|
| + return m_response.mimeType();
|
| }
|
|
|
| +// 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_frame->loader()->stopAllLoaders();
|
| + m_writer = createWriterFor(m_frame, ownerDocument, m_frame->document()->url(), mimeType(), m_writer ? m_writer->encoding() : "", m_writer ? m_writer->encodingWasChosenByUser() : false, true);
|
| + if (!source.isNull())
|
| + m_writer->appendReplacingData(source);
|
| + endWriting(m_writer.get());
|
| }
|
|
|
| } // namespace WebCore
|
|
|