This source file includes following definitions.
- isArchiveMIMEType
- m_applicationCacheHost
- frameLoader
- mainResourceLoader
- mainResourceIdentifier
- document
- originalRequest
- request
- url
- updateForSameDocumentNavigation
- urlForHistory
- setMainDocumentError
- mainReceivedError
- stopLoading
- commitIfReady
- isLoading
- notifyFinished
- finishedLoading
- isRedirectAfterPost
- shouldContinueForNavigationPolicy
- redirectReceived
- updateRequest
- isFormSubmission
- willSendRequest
- canShowMIMEType
- shouldContinueForResponse
- responseReceived
- ensureWriter
- commitData
- dataReceived
- checkLoadComplete
- clearRedirectChain
- appendRedirect
- detachFromFrame
- clearMainResourceLoader
- clearMainResourceHandle
- maybeCreateArchive
- addAllArchiveResources
- prepareSubframeArchiveLoadIfNeeded
- scheduleArchiveLoad
- responseMIMEType
- unreachableURL
- setDefersLoading
- maybeLoadEmpty
- startLoadingMainResource
- cancelMainResourceLoad
- attachThreadedDataReceiver
- endWriting
- createWriterFor
- mimeType
- setUserChosenEncoding
- replaceDocument
#include "config.h"
#include "core/loader/DocumentLoader.h"
#include "FetchInitiatorTypeNames.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentParser.h"
#include "core/events/Event.h"
#include "core/fetch/MemoryCache.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/ResourceLoader.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/parser/TextResourceDecoder.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/UniqueIdentifier.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
#include "core/frame/DOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "platform/Logging.h"
#include "platform/UserGestureIndicator.h"
#include "platform/mhtml/ArchiveResourceCollection.h"
#include "platform/mhtml/MHTMLArchive.h"
#include "platform/plugins/PluginData.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "public/platform/Platform.h"
#include "public/platform/WebMimeRegistry.h"
#include "public/platform/WebThreadedDataReceiver.h"
#include "wtf/Assertions.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
static bool isArchiveMIMEType(const String& mimeType)
{
return mimeType == "multipart/related";
}
DocumentLoader::DocumentLoader(LocalFrame* frame, const ResourceRequest& req, const SubstituteData& substituteData)
: m_frame(frame)
, m_fetcher(ResourceFetcher::create(this))
, m_originalRequest(req)
, m_substituteData(substituteData)
, m_request(req)
, m_committed(false)
, m_isClientRedirect(false)
, m_replacesCurrentHistoryItem(false)
, m_loadingMainResource(false)
, m_timeOfLastDataReceived(0.0)
, m_applicationCacheHost(adoptPtr(new ApplicationCacheHost(this)))
{
}
FrameLoader* DocumentLoader::frameLoader() const
{
if (!m_frame)
return 0;
return &m_frame->loader();
}
ResourceLoader* DocumentLoader::mainResourceLoader() const
{
return m_mainResource ? m_mainResource->loader() : 0;
}
DocumentLoader::~DocumentLoader()
{
ASSERT(!m_frame || !isLoading());
m_fetcher->clearDocumentLoader();
clearMainResourceHandle();
}
unsigned long DocumentLoader::mainResourceIdentifier() const
{
return m_mainResource ? m_mainResource->identifier() : 0;
}
Document* DocumentLoader::document() const
{
if (m_frame && m_frame->loader().documentLoader() == this)
return m_frame->document();
return 0;
}
const ResourceRequest& DocumentLoader::originalRequest() const
{
return m_originalRequest;
}
const ResourceRequest& DocumentLoader::request() const
{
return m_request;
}
const KURL& DocumentLoader::url() const
{
return m_request.url();
}
void DocumentLoader::updateForSameDocumentNavigation(const KURL& newURL)
{
KURL oldURL = m_request.url();
m_originalRequest.setURL(newURL);
m_request.setURL(newURL);
clearRedirectChain();
if (m_isClientRedirect)
appendRedirect(oldURL);
appendRedirect(newURL);
}
const KURL& DocumentLoader::urlForHistory() const
{
return unreachableURL().isEmpty() ? url() : unreachableURL();
}
void DocumentLoader::setMainDocumentError(const ResourceError& error)
{
m_mainDocumentError = error;
}
void DocumentLoader::mainReceivedError(const ResourceError& error)
{
ASSERT(!error.isNull());
ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading() || InspectorInstrumentation::isDebuggerPaused(m_frame));
m_applicationCacheHost->failedLoadingMainResource();
if (!frameLoader())
return;
setMainDocumentError(error);
clearMainResourceLoader();
frameLoader()->receivedMainResourceError(error);
clearMainResourceHandle();
}
void DocumentLoader::stopLoading()
{
RefPtr<LocalFrame> protectFrame(m_frame);
RefPtr<DocumentLoader> protectLoader(this);
bool loading = isLoading();
if (m_committed) {
Document* doc = m_frame->document();
if (loading || doc->parsing())
m_frame->loader().stopLoading();
}
if (!loading)
return;
if (m_loadingMainResource) {
cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
} else if (m_fetcher->isFetching()) {
setMainDocumentError(ResourceError::cancelledError(m_request.url()));
} else {
mainReceivedError(ResourceError::cancelledError(m_request.url()));
}
m_fetcher->stopFetching();
}
void DocumentLoader::commitIfReady()
{
if (!m_committed) {
m_committed = true;
frameLoader()->commitProvisionalLoad();
}
}
bool DocumentLoader::isLoading() const
{
if (document() && document()->hasActiveParser())
return true;
return m_loadingMainResource || m_fetcher->isFetching();
}
void DocumentLoader::notifyFinished(Resource* resource)
{
ASSERT_UNUSED(resource, m_mainResource == resource);
ASSERT(m_mainResource);
RefPtr<DocumentLoader> protect(this);
if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
finishedLoading(m_mainResource->loadFinishTime());
return;
}
mainReceivedError(m_mainResource->resourceError());
}
void DocumentLoader::finishedLoading(double finishTime)
{
ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading() || InspectorInstrumentation::isDebuggerPaused(m_frame));
RefPtr<DocumentLoader> protect(this);
double responseEndTime = finishTime;
if (!responseEndTime)
responseEndTime = m_timeOfLastDataReceived;
if (!responseEndTime)
responseEndTime = monotonicallyIncreasingTime();
timing()->setResponseEnd(responseEndTime);
commitIfReady();
if (!frameLoader())
return;
if (!maybeCreateArchive()) {
if (!m_writer)
commitData(0, 0);
}
endWriting(m_writer.get());
if (!m_mainDocumentError.isNull())
return;
clearMainResourceLoader();
if (!frameLoader()->stateMachine()->creatingInitialEmptyDocument())
frameLoader()->checkLoadComplete();
if (m_frame) {
if (m_mainResource && m_frame->document()->hasManifest())
memoryCache()->remove(m_mainResource.get());
}
m_applicationCacheHost->finishedLoadingMainResource();
clearMainResourceHandle();
}
bool DocumentLoader::isRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
int status = redirectResponse.httpStatusCode();
if (((status >= 301 && status <= 303) || status == 307)
&& m_originalRequest.httpMethod() == "POST")
return true;
return false;
}
bool DocumentLoader::shouldContinueForNavigationPolicy(const ResourceRequest& request)
{
if (request.url().isEmpty() || m_substituteData.isValid())
return true;
if (m_frame->ownerElement() && !m_frame->ownerElement()->document().contentSecurityPolicy()->allowChildFrameFromSource(request.url())) {
m_frame->document()->enforceSandboxFlags(SandboxOrigin);
m_frame->ownerElement()->dispatchEvent(Event::create(EventTypeNames::load));
return false;
}
NavigationPolicy policy = m_triggeringAction.policy();
policy = frameLoader()->client()->decidePolicyForNavigation(request, this, policy);
if (policy == NavigationPolicyCurrentTab)
return true;
if (policy == NavigationPolicyIgnore)
return false;
if (!DOMWindow::allowPopUp(*m_frame) && !UserGestureIndicator::processingUserGesture())
return false;
frameLoader()->client()->loadURLExternally(request, policy);
return false;
}
void DocumentLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
ASSERT_UNUSED(resource, resource == m_mainResource);
willSendRequest(request, redirectResponse);
}
void DocumentLoader::updateRequest(Resource* resource, const ResourceRequest& request)
{
ASSERT_UNUSED(resource, resource == m_mainResource);
m_request = request;
}
static bool isFormSubmission(NavigationType type)
{
return type == NavigationTypeFormSubmitted || type == NavigationTypeFormResubmitted;
}
void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
ASSERT(!newRequest.isNull());
if (isFormSubmission(m_triggeringAction.type()) && !m_frame->document()->contentSecurityPolicy()->allowFormAction(newRequest.url())) {
cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
return;
}
ASSERT(timing()->fetchStart());
if (!redirectResponse.isNull()) {
RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
if (!redirectingOrigin->canDisplay(newRequest.url())) {
FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
return;
}
timing()->addRedirect(redirectResponse.url(), newRequest.url());
}
if (frameLoader()->isLoadingMainFrame())
newRequest.setFirstPartyForCookies(newRequest.url());
if (newRequest.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(newRequest, redirectResponse))
newRequest.setCachePolicy(ReloadIgnoringCacheData);
if (m_frame->tree().parent()) {
LocalFrame* top = m_frame->tree().top();
if (!top->loader().mixedContentChecker()->canRunInsecureContent(top->document()->securityOrigin(), newRequest.url())) {
cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
return;
}
}
m_request = newRequest;
if (redirectResponse.isNull())
return;
appendRedirect(newRequest.url());
frameLoader()->client()->dispatchDidReceiveServerRedirectForProvisionalLoad();
if (!shouldContinueForNavigationPolicy(newRequest))
cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
}
static bool canShowMIMEType(const String& mimeType, Page* page)
{
if (blink::Platform::current()->mimeRegistry()->supportsMIMEType(mimeType) == blink::WebMimeRegistry::IsSupported)
return true;
PluginData* pluginData = page->pluginData();
return !mimeType.isEmpty() && pluginData && pluginData->supportsMimeType(mimeType);
}
bool DocumentLoader::shouldContinueForResponse() const
{
if (m_substituteData.isValid())
return true;
int statusCode = m_response.httpStatusCode();
if (statusCode == 204 || statusCode == 205) {
return false;
}
if (contentDispositionType(m_response.httpHeaderField("Content-Disposition")) == ContentDispositionAttachment) {
return false;
}
if (!canShowMIMEType(m_response.mimeType(), m_frame->page()))
return false;
if (equalIgnoringCase("multipart/related", m_response.mimeType()) && !SchemeRegistry::shouldTreatURLSchemeAsLocal(m_request.url().protocol()))
return false;
return true;
}
void DocumentLoader::responseReceived(Resource* resource, const ResourceResponse& response)
{
ASSERT_UNUSED(resource, m_mainResource == resource);
RefPtr<DocumentLoader> protect(this);
m_applicationCacheHost->didReceiveResponseForMainResource(response);
if (response.appCacheID())
memoryCache()->remove(m_mainResource.get());
DEFINE_STATIC_LOCAL(AtomicString, xFrameOptionHeader, ("x-frame-options", AtomicString::ConstructFromLiteral));
HTTPHeaderMap::const_iterator it = response.httpHeaderFields().find(xFrameOptionHeader);
if (it != response.httpHeaderFields().end()) {
String content = it->value;
ASSERT(m_mainResource);
unsigned long identifier = mainResourceIdentifier();
ASSERT(identifier);
if (frameLoader()->shouldInterruptLoadForXFrameOptions(content, response.url(), identifier)) {
InspectorInstrumentation::continueAfterXFrameOptionsDenied(m_frame, this, identifier, response);
String message = "Refused to display '" + response.url().elidedString() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
frame()->document()->addConsoleMessageWithRequestIdentifier(SecurityMessageSource, ErrorMessageLevel, message, identifier);
frame()->document()->enforceSandboxFlags(SandboxOrigin);
if (HTMLFrameOwnerElement* ownerElement = frame()->ownerElement())
ownerElement->dispatchEvent(Event::create(EventTypeNames::load));
if (frameLoader())
cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
return;
}
}
ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
m_response = response;
if (isArchiveMIMEType(m_response.mimeType()) && m_mainResource->dataBufferingPolicy() != BufferData)
m_mainResource->setDataBufferingPolicy(BufferData);
if (!shouldContinueForResponse()) {
InspectorInstrumentation::continueWithPolicyIgnore(m_frame, this, m_mainResource->identifier(), m_response);
cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
return;
}
if (m_response.isHTTP()) {
int status = m_response.httpStatusCode();
if ((status < 200 || status >= 300) && m_frame->ownerElement() && m_frame->ownerElement()->isObjectElement()) {
m_frame->ownerElement()->renderFallbackContent();
cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
}
}
}
void DocumentLoader::ensureWriter(const AtomicString& mimeType, const KURL& overridingURL)
{
if (m_writer)
return;
const AtomicString& encoding = overrideEncoding().isNull() ? response().textEncodingName() : overrideEncoding();
m_writer = createWriterFor(m_frame, 0, url(), mimeType, encoding, false, false);
m_writer->setDocumentWasLoadedAsPartOfNavigation();
if (!overridingURL.isEmpty())
m_frame->document()->setBaseURLOverride(overridingURL);
frameLoader()->receivedFirstData();
m_frame->document()->maybeHandleHttpRefresh(m_response.httpHeaderField("Refresh"), Document::HttpRefreshFromHeader);
}
void DocumentLoader::commitData(const char* bytes, size_t length)
{
ensureWriter(m_response.mimeType());
ASSERT(m_frame->document()->parsing());
m_writer->addData(bytes, length);
}
void DocumentLoader::dataReceived(Resource* resource, const char* data, int length)
{
ASSERT(data);
ASSERT(length);
ASSERT_UNUSED(resource, resource == m_mainResource);
ASSERT(!m_response.isNull());
ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
RefPtr<LocalFrame> protectFrame(m_frame);
RefPtr<DocumentLoader> protectLoader(this);
m_applicationCacheHost->mainResourceDataReceived(data, length);
m_timeOfLastDataReceived = monotonicallyIncreasingTime();
commitIfReady();
if (!frameLoader())
return;
if (isArchiveMIMEType(response().mimeType()))
return;
commitData(data, length);
if (m_frame && m_frame->document()->isMediaDocument())
cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
}
void DocumentLoader::checkLoadComplete()
{
if (!m_frame || isLoading() || !m_committed)
return;
m_frame->domWindow()->finishedLoading();
}
void DocumentLoader::clearRedirectChain()
{
m_redirectChain.clear();
}
void DocumentLoader::appendRedirect(const KURL& url)
{
m_redirectChain.append(url);
}
void DocumentLoader::detachFromFrame()
{
ASSERT(m_frame);
RefPtr<LocalFrame> protectFrame(m_frame);
RefPtr<DocumentLoader> protectLoader(this);
stopLoading();
m_applicationCacheHost->setApplicationCache(0);
InspectorInstrumentation::loaderDetachedFromFrame(m_frame, this);
m_frame = 0;
}
void DocumentLoader::clearMainResourceLoader()
{
m_loadingMainResource = false;
checkLoadComplete();
}
void DocumentLoader::clearMainResourceHandle()
{
if (!m_mainResource)
return;
m_mainResource->removeClient(this);
m_mainResource = 0;
}
bool DocumentLoader::maybeCreateArchive()
{
if (m_frame->tree().parent())
return false;
if (!isArchiveMIMEType(m_response.mimeType()))
return false;
ASSERT(m_mainResource);
m_archive = MHTMLArchive::create(m_response.url(), m_mainResource->resourceBuffer());
if (!m_archive || !m_archive->mainResource()) {
m_archive.clear();
return false;
}
addAllArchiveResources(m_archive.get());
ArchiveResource* mainResource = m_archive->mainResource();
ensureWriter(mainResource->mimeType(), m_archive->mainResource()->url());
document()->enforceSandboxFlags(SandboxAll);
commitData(mainResource->data()->data(), mainResource->data()->size());
return true;
}
void DocumentLoader::addAllArchiveResources(MHTMLArchive* archive)
{
ASSERT(archive);
if (!m_archiveResourceCollection)
m_archiveResourceCollection = adoptPtr(new ArchiveResourceCollection);
m_archiveResourceCollection->addAllResources(archive);
}
void DocumentLoader::prepareSubframeArchiveLoadIfNeeded()
{
if (!m_frame->tree().parent())
return;
ArchiveResourceCollection* parentCollection = m_frame->tree().parent()->loader().documentLoader()->m_archiveResourceCollection.get();
if (!parentCollection)
return;
m_archive = parentCollection->popSubframeArchive(m_frame->tree().uniqueName(), m_request.url());
if (!m_archive)
return;
addAllArchiveResources(m_archive.get());
ArchiveResource* mainResource = m_archive->mainResource();
m_substituteData = SubstituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
}
bool DocumentLoader::scheduleArchiveLoad(Resource* cachedResource, const ResourceRequest& request)
{
if (!m_archive)
return false;
ASSERT(m_archiveResourceCollection);
ArchiveResource* archiveResource = m_archiveResourceCollection->archiveResourceForURL(request.url());
if (!archiveResource) {
cachedResource->error(Resource::LoadError);
return true;
}
cachedResource->setLoading(true);
cachedResource->responseReceived(archiveResource->response());
SharedBuffer* data = archiveResource->data();
if (data)
cachedResource->appendData(data->data(), data->size());
cachedResource->finish();
return true;
}
const AtomicString& DocumentLoader::responseMIMEType() const
{
return m_response.mimeType();
}
const KURL& DocumentLoader::unreachableURL() const
{
return m_substituteData.failingURL();
}
void DocumentLoader::setDefersLoading(bool defers)
{
if (mainResourceLoader() && mainResourceLoader()->isLoadedBy(m_fetcher.get()))
mainResourceLoader()->setDefersLoading(defers);
m_fetcher->setDefersLoading(defers);
}
bool DocumentLoader::maybeLoadEmpty()
{
bool shouldLoadEmpty = !m_substituteData.isValid() && (m_request.url().isEmpty() || SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(m_request.url().protocol()));
if (!shouldLoadEmpty)
return false;
if (m_request.url().isEmpty() && !frameLoader()->stateMachine()->creatingInitialEmptyDocument())
m_request.setURL(blankURL());
m_response = ResourceResponse(m_request.url(), "text/html", 0, nullAtom, String());
finishedLoading(monotonicallyIncreasingTime());
return true;
}
void DocumentLoader::startLoadingMainResource()
{
RefPtr<DocumentLoader> protect(this);
m_mainDocumentError = ResourceError();
timing()->markNavigationStart();
ASSERT(!m_mainResource);
ASSERT(!m_loadingMainResource);
m_loadingMainResource = true;
if (maybeLoadEmpty())
return;
ASSERT(timing()->navigationStart());
ASSERT(!timing()->fetchStart());
timing()->markFetchStart();
willSendRequest(m_request, ResourceResponse());
if (!m_frame || m_request.isNull())
return;
m_applicationCacheHost->willStartLoadingMainResource(m_request);
prepareSubframeArchiveLoadIfNeeded();
ResourceRequest request(m_request);
DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions,
(SniffContent, DoNotBufferData, AllowStoredCredentials, ClientRequestedCredentials, CheckContentSecurityPolicy, DocumentContext));
FetchRequest cachedResourceRequest(request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
m_mainResource = m_fetcher->fetchMainResource(cachedResourceRequest, m_substituteData);
if (!m_mainResource) {
m_request = ResourceRequest();
m_applicationCacheHost = adoptPtr(new ApplicationCacheHost(this));
maybeLoadEmpty();
return;
}
m_mainResource->addClient(this);
if (mainResourceLoader())
request = mainResourceLoader()->originalRequest();
if (equalIgnoringFragmentIdentifier(m_request.url(), request.url()))
request.setURL(m_request.url());
m_request = request;
}
void DocumentLoader::cancelMainResourceLoad(const ResourceError& resourceError)
{
RefPtr<DocumentLoader> protect(this);
ResourceError error = resourceError.isNull() ? ResourceError::cancelledError(m_request.url()) : resourceError;
if (mainResourceLoader())
mainResourceLoader()->cancel(error);
mainReceivedError(error);
}
void DocumentLoader::attachThreadedDataReceiver(PassOwnPtr<blink::WebThreadedDataReceiver> threadedDataReceiver)
{
if (mainResourceLoader())
mainResourceLoader()->attachThreadedDataReceiver(threadedDataReceiver);
}
void DocumentLoader::endWriting(DocumentWriter* writer)
{
ASSERT_UNUSED(writer, m_writer == writer);
m_writer->end();
m_writer.clear();
}
PassRefPtr<DocumentWriter> DocumentLoader::createWriterFor(LocalFrame* frame, const Document* ownerDocument, const KURL& url, const AtomicString& mimeType, const AtomicString& encoding, bool userChosen, bool dispatch)
{
DocumentInit init(url, frame);
init.withNewRegistrationContext();
bool shouldReuseDefaultView = frame->loader().stateMachine()->isDisplayingInitialEmptyDocument() && frame->document()->isSecureTransitionTo(url);
frame->loader().clear();
if (frame->document())
frame->document()->prepareForDestruction();
if (!shouldReuseDefaultView)
frame->setDOMWindow(DOMWindow::create(*frame));
RefPtr<Document> document = frame->domWindow()->installNewDocument(mimeType, init);
if (ownerDocument) {
document->setCookieURL(ownerDocument->cookieURL());
document->setSecurityOrigin(ownerDocument->securityOrigin());
}
frame->loader().didBeginDocument(dispatch);
return DocumentWriter::create(document.get(), mimeType, encoding, userChosen);
}
const AtomicString& DocumentLoader::mimeType() const
{
if (m_writer)
return m_writer->mimeType();
return m_response.mimeType();
}
void DocumentLoader::setUserChosenEncoding(const String& charset)
{
if (m_writer)
m_writer->setUserChosenEncoding(charset);
}
void DocumentLoader::replaceDocument(const String& source, Document* ownerDocument)
{
m_frame->loader().stopAllLoaders();
m_writer = createWriterFor(m_frame, ownerDocument, m_frame->document()->url(), mimeType(), m_writer ? m_writer->encoding() : emptyAtom, m_writer ? m_writer->encodingWasChosenByUser() : false, true);
if (!source.isNull())
m_writer->appendReplacingData(source);
endWriting(m_writer.get());
}
}