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 |