/*
 * Copyright (C) 2013 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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/html/imports/HTMLImportLoader.h"

#include "core/dom/Document.h"
#include "core/dom/DocumentParser.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/custom/V0CustomElementSyncMicrotaskQueue.h"
#include "core/html/HTMLDocument.h"
#include "core/html/imports/HTMLImportChild.h"
#include "core/html/imports/HTMLImportsController.h"
#include "core/loader/DocumentWriter.h"
#include "platform/network/ContentSecurityPolicyResponseHeaders.h"


namespace blink {

HTMLImportLoader::HTMLImportLoader(HTMLImportsController* controller)
    : m_controller(controller)
    , m_state(StateLoading)
    , m_microtaskQueue(V0CustomElementSyncMicrotaskQueue::create())
{
}

HTMLImportLoader::~HTMLImportLoader()
{
}

void HTMLImportLoader::dispose()
{
    m_controller = nullptr;
    if (m_document) {
        if (m_document->parser())
            m_document->parser()->removeClient(this);
        m_document->setImportsController(nullptr);
        m_document.clear();
    }
    clearResource();
}

void HTMLImportLoader::startLoading(RawResource* resource)
{
    setResource(resource);
}

void HTMLImportLoader::responseReceived(Resource* resource, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
{
    ASSERT_UNUSED(handle, !handle);
    // Resource may already have been loaded with the import loader
    // being added as a client later & now being notified. Fail early.
    if (resource->loadFailedOrCanceled() || response.httpStatusCode() >= 400 || !response.httpHeaderField(HTTPNames::Content_Disposition).isNull()) {
        setState(StateError);
        return;
    }
    setState(startWritingAndParsing(response));
}

void HTMLImportLoader::dataReceived(Resource*, const char* data, size_t length)
{
    m_writer->addData(data, length);
}

void HTMLImportLoader::notifyFinished(Resource* resource)
{
    // The writer instance indicates that a part of the document can be already loaded.
    // We don't take such a case as an error because the partially-loaded document has been visible from script at this point.
    if (resource->loadFailedOrCanceled() && !m_writer) {
        setState(StateError);
        return;
    }

    setState(finishWriting());
}

HTMLImportLoader::State HTMLImportLoader::startWritingAndParsing(const ResourceResponse& response)
{
    ASSERT(m_controller);
    ASSERT(!m_imports.isEmpty());
    DocumentInit init = DocumentInit(response.url(), 0, m_controller->master()->contextDocument(), m_controller)
        .withRegistrationContext(m_controller->master()->registrationContext());
    m_document = HTMLDocument::create(init);
    m_writer = DocumentWriter::create(m_document.get(), AllowAsynchronousParsing, response.mimeType(), "UTF-8");

    DocumentParser* parser = m_document->parser();
    ASSERT(parser);
    parser->addClient(this);

    return StateLoading;
}

HTMLImportLoader::State HTMLImportLoader::finishWriting()
{
    return StateWritten;
}

HTMLImportLoader::State HTMLImportLoader::finishParsing()
{
    return StateParsed;
}

HTMLImportLoader::State HTMLImportLoader::finishLoading()
{
    return StateLoaded;
}

void HTMLImportLoader::setState(State state)
{
    if (m_state == state)
        return;

    m_state = state;

    if (m_state == StateParsed || m_state == StateError || m_state == StateWritten) {
        if (DocumentWriter* writer = m_writer.release())
            writer->end();
    }

    // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here.
    if (state == StateLoaded)
        m_document->setReadyState(Document::Complete);
    if (state == StateLoaded || state == StateError)
        didFinishLoading();
}

void HTMLImportLoader::notifyParserStopped()
{
    setState(finishParsing());
    if (!hasPendingResources())
        setState(finishLoading());

    DocumentParser* parser = m_document->parser();
    ASSERT(parser);
    parser->removeClient(this);
}

void HTMLImportLoader::didRemoveAllPendingStylesheet()
{
    if (m_state == StateParsed)
        setState(finishLoading());
}

bool HTMLImportLoader::hasPendingResources() const
{
    return m_document && m_document->styleEngine().hasPendingSheets();
}

void HTMLImportLoader::didFinishLoading()
{
    for (size_t i = 0; i < m_imports.size(); ++i)
        m_imports[i]->didFinishLoading();

    clearResource();

    ASSERT(!m_document || !m_document->parsing());
}

void HTMLImportLoader::moveToFirst(HTMLImportChild* import)
{
    size_t position = m_imports.find(import);
    ASSERT(kNotFound != position);
    m_imports.remove(position);
    m_imports.insert(0, import);
}

void HTMLImportLoader::addImport(HTMLImportChild* import)
{
    ASSERT(kNotFound == m_imports.find(import));

    m_imports.append(import);
    import->normalize();
    if (isDone())
        import->didFinishLoading();
}

void HTMLImportLoader::removeImport(HTMLImportChild* client)
{
    ASSERT(kNotFound != m_imports.find(client));
    m_imports.remove(m_imports.find(client));
}

bool HTMLImportLoader::shouldBlockScriptExecution() const
{
    return firstImport()->state().shouldBlockScriptExecution();
}

V0CustomElementSyncMicrotaskQueue* HTMLImportLoader::microtaskQueue() const
{
    return m_microtaskQueue;
}

DEFINE_TRACE(HTMLImportLoader)
{
    visitor->trace(m_controller);
    visitor->trace(m_imports);
    visitor->trace(m_document);
    visitor->trace(m_writer);
    visitor->trace(m_microtaskQueue);
    DocumentParserClient::trace(visitor);
    ResourceOwner<RawResource>::trace(visitor);
}

} // namespace blink
