/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/loader/DocumentLoader.h"

#include "core/dom/Document.h"
#include "core/dom/DocumentParser.h"
#include "core/dom/WeakIdentifierMap.h"
#include "core/events/Event.h"
#include "core/fetch/CSSStyleSheetResource.h"
#include "core/fetch/FetchInitiatorTypeNames.h"
#include "core/fetch/FetchRequest.h"
#include "core/fetch/FontResource.h"
#include "core/fetch/ImageResource.h"
#include "core/fetch/MemoryCache.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/ResourceLoader.h"
#include "core/fetch/ScriptResource.h"
#include "core/frame/FrameHost.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/parser/HTMLDocumentParser.h"
#include "core/html/parser/TextResourceDecoder.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/loader/FrameFetchContext.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/LinkLoader.h"
#include "core/loader/ProgressTracker.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "platform/HTTPNames.h"
#include "platform/Logging.h"
#include "platform/UserGestureIndicator.h"
#include "platform/mhtml/ArchiveResource.h"
#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
#include "platform/network/HTTPParsers.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 "wtf/Assertions.h"
#include "wtf/TemporaryChange.h"
#include "wtf/text/WTFString.h"

namespace blink {

static bool isArchiveMIMEType(const String& mimeType)
{
    return equalIgnoringCase("multipart/related", mimeType);
}

static bool shouldInheritSecurityOriginFromOwner(const KURL& url)
{
    // https://html.spec.whatwg.org/multipage/browsers.html#origin
    //
    // If a Document is the initial "about:blank" document
    //     The origin and effective script origin of the Document are those it
    //     was assigned when its browsing context was created.
    //
    // Note: We generalize this to all "blank" URLs and invalid URLs because we
    // treat all of these URLs as about:blank.
    return url.isEmpty() || url.protocolIsAbout();
}

DocumentLoader::DocumentLoader(LocalFrame* frame, const ResourceRequest& req, const SubstituteData& substituteData)
    : m_frame(frame)
    , m_fetcher(FrameFetchContext::createContextAndFetcher(this, nullptr))
    , m_originalRequest(req)
    , m_substituteData(substituteData)
    , m_request(req)
    , m_isClientRedirect(false)
    , m_replacesCurrentHistoryItem(false)
    , m_navigationType(NavigationTypeOther)
    , m_documentLoadTiming(*this)
    , m_timeOfLastDataReceived(0.0)
    , m_applicationCacheHost(ApplicationCacheHost::create(this))
    , m_wasBlockedAfterXFrameOptionsOrCSP(false)
    , m_state(NotStarted)
    , m_inDataReceived(false)
    , m_dataBuffer(SharedBuffer::create())
{
}

FrameLoader* DocumentLoader::frameLoader() const
{
    if (!m_frame)
        return nullptr;
    return &m_frame->loader();
}

ResourceLoader* DocumentLoader::mainResourceLoader() const
{
    return m_mainResource ? m_mainResource->loader() : nullptr;
}

DocumentLoader::~DocumentLoader()
{
    ASSERT(!m_frame);
    ASSERT(!m_mainResource);
    ASSERT(!m_applicationCacheHost);
}

DEFINE_TRACE(DocumentLoader)
{
    visitor->trace(m_frame);
    visitor->trace(m_fetcher);
    visitor->trace(m_mainResource);
    visitor->trace(m_writer);
    visitor->trace(m_documentLoadTiming);
    visitor->trace(m_applicationCacheHost);
    visitor->trace(m_contentSecurityPolicy);
}

unsigned long DocumentLoader::mainResourceIdentifier() const
{
    return m_mainResource ? m_mainResource->identifier() : 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();
}

Resource* DocumentLoader::startPreload(Resource::Type type, FetchRequest& request)
{
    Resource* resource = nullptr;
    switch (type) {
    case Resource::Image:
        resource = ImageResource::fetch(request, fetcher());
        break;
    case Resource::Script:
        resource = ScriptResource::fetch(request, fetcher());
        break;
    case Resource::CSSStyleSheet:
        resource = CSSStyleSheetResource::fetch(request, fetcher());
        break;
    case Resource::Font:
        resource = FontResource::fetch(request, fetcher());
        break;
    case Resource::Media:
        resource = RawResource::fetchMedia(request, fetcher());
        break;
    case Resource::TextTrack:
        resource = RawResource::fetchTextTrack(request, fetcher());
        break;
    case Resource::ImportResource:
        resource = RawResource::fetchImport(request, fetcher());
        break;
    case Resource::LinkPreload:
        resource = RawResource::fetch(request, fetcher());
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    if (resource)
        fetcher()->preloadStarted(resource);
    return resource;
}

void DocumentLoader::didChangePerformanceTiming()
{
    if (frame() && frame()->isMainFrame() && m_state >= Committed) {
        frameLoader()->client()->didChangePerformanceTiming();
    }
}

void DocumentLoader::didObserveLoadingBehavior(WebLoadingBehaviorFlag behavior)
{
    if (frame() && frame()->isMainFrame()) {
        ASSERT(m_state >= Committed);
        frameLoader()->client()->didObserveLoadingBehavior(behavior);
    }
}

void DocumentLoader::updateForSameDocumentNavigation(const KURL& newURL, SameDocumentNavigationSource sameDocumentNavigationSource)
{
    KURL oldURL = m_request.url();
    m_originalRequest.setURL(newURL);
    m_request.setURL(newURL);
    if (sameDocumentNavigationSource == SameDocumentNavigationHistoryApi) {
        m_request.setHTTPMethod(HTTPNames::GET);
        m_request.setHTTPBody(nullptr);
    }
    clearRedirectChain();
    if (m_isClientRedirect)
        appendRedirect(oldURL);
    appendRedirect(newURL);
}

const KURL& DocumentLoader::urlForHistory() const
{
    return unreachableURL().isEmpty() ? url() : unreachableURL();
}

void DocumentLoader::commitIfReady()
{
    if (m_state < Committed) {
        m_state = Committed;
        frameLoader()->commitProvisionalLoad();
    }
}

void DocumentLoader::notifyFinished(Resource* resource)
{
    ASSERT_UNUSED(resource, m_mainResource == resource);
    ASSERT(m_mainResource);

    if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
        finishedLoading(m_mainResource->loadFinishTime());
        return;
    }

    if (m_applicationCacheHost)
        m_applicationCacheHost->failedLoadingMainResource();
    m_state = MainResourceDone;
    frameLoader()->loadFailed(this, m_mainResource->resourceError());
    clearMainResourceHandle();
}

void DocumentLoader::finishedLoading(double finishTime)
{
    ASSERT(!m_frame->page()->defersLoading() || InspectorInstrumentation::isDebuggerPaused(m_frame));

    double responseEndTime = finishTime;
    if (!responseEndTime)
        responseEndTime = m_timeOfLastDataReceived;
    if (!responseEndTime)
        responseEndTime = monotonicallyIncreasingTime();
    timing().setResponseEnd(responseEndTime);

    commitIfReady();
    if (!frameLoader())
        return;

    if (!maybeCreateArchive()) {
        // 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_writer)
            commitData(0, 0);
    }

    if (!m_frame)
        return;

    m_applicationCacheHost->finishedLoadingMainResource();
    endWriting(m_writer.get());
    if (m_state < MainResourceDone)
        m_state = MainResourceDone;
    clearMainResourceHandle();
}

void DocumentLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
    ASSERT_UNUSED(resource, resource == m_mainResource);
    ASSERT(!redirectResponse.isNull());
    m_request = request;

    // If the redirecting url is not allowed to display content from the target origin,
    // then block the redirect.
    const KURL& requestURL = m_request.url();
    RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
    if (!redirectingOrigin->canDisplay(requestURL)) {
        FrameLoader::reportLocalLoadFailed(m_frame, requestURL.getString());
        m_fetcher->stopFetching();
        return;
    }
    if (!frameLoader()->shouldContinueForNavigationPolicy(m_request, SubstituteData(), this, CheckContentSecurityPolicy, m_navigationType, NavigationPolicyCurrentTab, replacesCurrentHistoryItem(), isClientRedirect())) {
        m_fetcher->stopFetching();
        return;
    }

    ASSERT(timing().fetchStart());
    timing().addRedirect(redirectResponse.url(), requestURL);
    appendRedirect(requestURL);
    frameLoader()->receivedMainResourceRedirect(requestURL);
}

static bool canShowMIMEType(const String& mimeType, Page* page)
{
    if (Platform::current()->mimeRegistry()->supportsMIMEType(mimeType) == 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) {
        // The server does not want us to replace the page contents.
        return false;
    }

    if (getContentDispositionType(m_response.httpHeaderField(HTTPNames::Content_Disposition)) == ContentDispositionAttachment) {
        // The server wants us to download instead of replacing the page contents.
        // Downloading is handled by the embedder, but we still get the initial
        // response so that we can ignore it and clean up properly.
        return false;
    }

    if (!canShowMIMEType(m_response.mimeType(), m_frame->page()))
        return false;
    return true;
}

void DocumentLoader::cancelLoadAfterXFrameOptionsOrCSPDenied(const ResourceResponse& response)
{
    InspectorInstrumentation::continueAfterXFrameOptionsDenied(m_frame, this, mainResourceIdentifier(), response);

    setWasBlockedAfterXFrameOptionsOrCSP();

    // Pretend that this was an empty HTTP 200 response.
    clearMainResourceHandle();
    m_response = ResourceResponse(blankURL(), "text/html", 0, nullAtom, String());
    finishedLoading(monotonicallyIncreasingTime());

    return;
}

void DocumentLoader::responseReceived(Resource* resource, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
{
    ASSERT_UNUSED(resource, m_mainResource == resource);
    ASSERT_UNUSED(handle, !handle);
    ASSERT(frame());

    m_applicationCacheHost->didReceiveResponseForMainResource(response);

    // The memory cache doesn't understand the application cache or its caching rules. So if a main resource is served
    // from the application cache, ensure we don't save the result for future use. All responses loaded
    // from appcache will have a non-zero appCacheID().
    if (response.appCacheID())
        memoryCache()->remove(m_mainResource.get());

    m_contentSecurityPolicy = ContentSecurityPolicy::create();
    m_contentSecurityPolicy->setOverrideURLForSelf(response.url());
    m_contentSecurityPolicy->didReceiveHeaders(ContentSecurityPolicyResponseHeaders(response));
    if (!m_contentSecurityPolicy->allowAncestors(m_frame, response.url())) {
        cancelLoadAfterXFrameOptionsOrCSPDenied(response);
        return;
    }

    // 'frame-ancestors' obviates 'x-frame-options': https://w3c.github.io/webappsec/specs/content-security-policy/#frame-ancestors-and-frame-options
    if (!m_contentSecurityPolicy->isFrameAncestorsEnforced()) {
        HTTPHeaderMap::const_iterator it = response.httpHeaderFields().find(HTTPNames::X_Frame_Options);
        if (it != response.httpHeaderFields().end()) {
            String content = it->value;
            if (frameLoader()->shouldInterruptLoadForXFrameOptions(content, response.url(), mainResourceIdentifier())) {
                String message = "Refused to display '" + response.url().elidedString() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
                ConsoleMessage* consoleMessage = ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message);
                consoleMessage->setRequestIdentifier(mainResourceIdentifier());
                frame()->document()->addConsoleMessage(consoleMessage);

                cancelLoadAfterXFrameOptionsOrCSPDenied(response);
                return;
            }
        }
    }

    ASSERT(!m_frame->page()->defersLoading());

    m_response = response;

    if (isArchiveMIMEType(m_response.mimeType()) && m_mainResource->getDataBufferingPolicy() != BufferData)
        m_mainResource->setDataBufferingPolicy(BufferData);

    if (!shouldContinueForResponse()) {
        InspectorInstrumentation::continueWithPolicyIgnore(m_frame, this, m_mainResource->identifier(), m_response);
        m_fetcher->stopFetching();
        return;
    }

    if (m_response.isHTTP()) {
        int status = m_response.httpStatusCode();
        if ((status < 200 || status >= 300) && m_frame->owner())
            m_frame->owner()->renderFallbackContent();
    }
}

void DocumentLoader::ensureWriter(const AtomicString& mimeType, const KURL& overridingURL)
{
    if (m_writer)
        return;

    const AtomicString& encoding = m_frame->host()->overrideEncoding().isNull() ? response().textEncodingName() : m_frame->host()->overrideEncoding();

    // Prepare a DocumentInit before clearing the frame, because it may need to
    // inherit an aliased security context.
    Document* owner = nullptr;
    // TODO(dcheng): This differs from the behavior of both IE and Firefox: the
    // origin is inherited from the document that loaded the URL.
    if (shouldInheritSecurityOriginFromOwner(url())) {
        Frame* ownerFrame = m_frame->tree().parent();
        if (!ownerFrame)
            ownerFrame = m_frame->loader().opener();
        if (ownerFrame && ownerFrame->isLocalFrame())
            owner = toLocalFrame(ownerFrame)->document();
    }
    DocumentInit init(owner, url(), m_frame);
    init.withNewRegistrationContext();
    m_frame->loader().clear();
    ASSERT(m_frame->page());

    ParserSynchronizationPolicy parsingPolicy = AllowAsynchronousParsing;
    if ((m_substituteData.isValid() && m_substituteData.forceSynchronousLoad()) || !Document::threadedParsingEnabledForTesting())
        parsingPolicy = ForceSynchronousParsing;

    m_writer = createWriterFor(init, mimeType, encoding, false, parsingPolicy);
    m_writer->setDocumentWasLoadedAsPartOfNavigation();

    // This should be set before receivedFirstData().
    if (!overridingURL.isEmpty())
        m_frame->document()->setBaseURLOverride(overridingURL);

    // Call receivedFirstData() exactly once per load.
    frameLoader()->receivedFirstData();
    m_frame->document()->maybeHandleHttpRefresh(m_response.httpHeaderField(HTTPNames::Refresh), Document::HttpRefreshFromHeader);
}

void DocumentLoader::commitData(const char* bytes, size_t length)
{
    ASSERT(m_state < MainResourceDone);
    ensureWriter(m_response.mimeType());

    // This can happen if document.close() is called by an event handler while
    // there's still pending incoming data.
    if (m_frame && !m_frame->document()->parsing())
        return;

    if (length)
        m_state = DataReceived;

    m_writer->addData(bytes, length);
}

void DocumentLoader::dataReceived(Resource* resource, const char* data, size_t length)
{
    ASSERT(data);
    ASSERT(length);
    ASSERT_UNUSED(resource, resource == m_mainResource);
    ASSERT(!m_response.isNull());
    ASSERT(!m_frame->page()->defersLoading());

    if (m_inDataReceived) {
        // If this function is reentered, defer processing of the additional
        // data to the top-level invocation. Reentrant calls can occur because
        // of web platform (mis-)features that require running a nested message
        // loop:
        // - alert(), confirm(), prompt()
        // - Detach of plugin elements.
        // - Synchronous XMLHTTPRequest
        m_dataBuffer->append(data, length);
        return;
    }

    TemporaryChange<bool> reentrancyProtector(m_inDataReceived, true);
    processData(data, length);

    // Process data received in reentrant invocations. Note that the
    // invocations of processData() may queue more data in reentrant
    // invocations, so iterate until it's empty.
    const char* segment;
    size_t pos = 0;
    while (size_t length = m_dataBuffer->getSomeData(segment, pos)) {
        processData(segment, length);
        pos += length;
    }
    // All data has been consumed, so flush the buffer.
    m_dataBuffer->clear();
}

void DocumentLoader::processData(const char* data, size_t length)
{
    m_applicationCacheHost->mainResourceDataReceived(data, length);
    m_timeOfLastDataReceived = monotonicallyIncreasingTime();

    if (isArchiveMIMEType(response().mimeType()))
        return;
    commitIfReady();
    if (!frameLoader())
        return;
    commitData(data, length);

    // If we are sending data to MediaDocument, we should stop here
    // and cancel the request.
    if (m_frame && m_frame->document()->isMediaDocument())
        m_fetcher->stopFetching();
}

void DocumentLoader::clearRedirectChain()
{
    m_redirectChain.clear();
}

void DocumentLoader::appendRedirect(const KURL& url)
{
    m_redirectChain.append(url);
}

void DocumentLoader::detachFromFrame()
{
    ASSERT(m_frame);

    // It never makes sense to have a document loader that is detached from its
    // frame have any loads active, so go ahead and kill all the loads.
    m_fetcher->stopFetching();

    // If that load cancellation triggered another detach, leave.
    // (fast/frames/detach-frame-nested-no-crash.html is an example of this.)
    if (!m_frame)
        return;

    m_fetcher->clearContext();
    m_applicationCacheHost->detachFromDocumentLoader();
    m_applicationCacheHost.clear();
    WeakIdentifierMap<DocumentLoader>::notifyObjectDestroyed(this);
    clearMainResourceHandle();
    m_frame = nullptr;
}

void DocumentLoader::clearMainResourceHandle()
{
    if (!m_mainResource)
        return;
    m_mainResource->removeClient(this);
    m_mainResource = nullptr;
}

bool DocumentLoader::maybeCreateArchive()
{
    // 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;

    ASSERT(m_mainResource);
    ArchiveResource* mainResource = m_fetcher->createArchive(m_mainResource.get());
    if (!mainResource)
        return false;
    // 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(), mainResource->url());

    // The Document has now been created.
    m_frame->document()->enforceSandboxFlags(SandboxAll);

    commitData(mainResource->data()->data(), mainResource->data()->size());
    return true;
}

const AtomicString& DocumentLoader::responseMIMEType() const
{
    return m_response.mimeType();
}

const KURL& DocumentLoader::unreachableURL() const
{
    return m_substituteData.failingURL();
}

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()
{
    timing().markNavigationStart();
    ASSERT(!m_mainResource);
    ASSERT(m_state == NotStarted);
    m_state = Provisional;

    if (maybeLoadEmpty())
        return;

    ASSERT(timing().navigationStart());
    ASSERT(!timing().fetchStart());
    timing().markFetchStart();

    m_applicationCacheHost->willStartLoadingMainResource(m_request);

    DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions,
        (DoNotBufferData, AllowStoredCredentials, ClientRequestedCredentials, CheckContentSecurityPolicy, DocumentContext));
    FetchRequest fetchRequest(m_request, FetchInitiatorTypeNames::document, mainResourceLoadOptions);
    m_mainResource = RawResource::fetchMainResource(fetchRequest, fetcher(), m_substituteData);
    if (!m_mainResource) {
        m_request = ResourceRequest();
        // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost
        // is now in a state where starting an empty load will be inconsistent. Replace it with
        // a new ApplicationCacheHost.
        if (m_applicationCacheHost)
            m_applicationCacheHost->detachFromDocumentLoader();
        m_applicationCacheHost = ApplicationCacheHost::create(this);
        maybeLoadEmpty();
        return;
    }
    // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
    // Even when using a cached resource, we may make some modification to the request, e.g. adding the referer header.
    m_request = mainResourceLoader() ? m_mainResource->resourceRequest() : fetchRequest.resourceRequest();
    m_mainResource->addClient(this);
}

void DocumentLoader::endWriting(DocumentWriter* writer)
{
    ASSERT_UNUSED(writer, m_writer == writer);
    m_writer->end();
    m_writer.clear();
}

DocumentWriter* DocumentLoader::createWriterFor(const DocumentInit& init, const AtomicString& mimeType, const AtomicString& encoding, bool dispatch, ParserSynchronizationPolicy parsingPolicy)
{
    LocalFrame* frame = init.frame();

    ASSERT(!frame->document() || !frame->document()->isActive());
    ASSERT(frame->tree().childCount() == 0);

    if (!init.shouldReuseDefaultView())
        frame->setDOMWindow(LocalDOMWindow::create(*frame));

    Document* document = frame->localDOMWindow()->installNewDocument(mimeType, init);

    frame->loader().didBeginDocument(dispatch);

    return DocumentWriter::create(document, parsingPolicy, mimeType, encoding);
}

const AtomicString& DocumentLoader::mimeType() const
{
    if (m_writer)
        return m_writer->mimeType();
    return m_response.mimeType();
}

// This is only called by FrameLoader::replaceDocumentWhileExecutingJavaScriptURL()
void DocumentLoader::replaceDocumentWhileExecutingJavaScriptURL(const DocumentInit& init, const String& source)
{
    m_writer = createWriterFor(init, mimeType(), m_writer ? m_writer->encoding() : emptyAtom, true, ForceSynchronousParsing);
    if (!source.isNull())
        m_writer->appendReplacingData(source);
    endWriting(m_writer.get());
}

DEFINE_WEAK_IDENTIFIER_MAP(DocumentLoader);

} // namespace blink
