/*
 * Copyright (C) 2000 Peter Kelly (pmk@post.com)
 * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "ProcessingInstruction.h"

#include "CSSStyleSheet.h"
#include "CachedCSSStyleSheet.h"
#include "CachedResourceLoader.h"
#include "CachedResourceRequest.h"
#include "CachedXSLStyleSheet.h"
#include "Document.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "MediaList.h"
#include "StyleScope.h"
#include "StyleSheetContents.h"
#include "XMLDocumentParser.h"
#include "XSLStyleSheet.h"
#include <wtf/SetForScope.h>

namespace WebCore {

inline ProcessingInstruction::ProcessingInstruction(Document& document, const String& target, const String& data)
    : CharacterData(document, data, CreateOther)
    , m_target(target)
{
}

Ref<ProcessingInstruction> ProcessingInstruction::create(Document& document, const String& target, const String& data)
{
    return adoptRef(*new ProcessingInstruction(document, target, data));
}

ProcessingInstruction::~ProcessingInstruction()
{
    if (m_sheet)
        m_sheet->clearOwnerNode();

    if (m_cachedSheet)
        m_cachedSheet->removeClient(*this);

    if (isConnected())
        document().styleScope().removeStyleSheetCandidateNode(*this);
}

String ProcessingInstruction::nodeName() const
{
    return m_target;
}

Node::NodeType ProcessingInstruction::nodeType() const
{
    return PROCESSING_INSTRUCTION_NODE;
}

Ref<Node> ProcessingInstruction::cloneNodeInternal(Document& targetDocument, CloningOperation)
{
    // FIXME: Is it a problem that this does not copy m_localHref?
    // What about other data members?
    return create(targetDocument, m_target, data());
}

void ProcessingInstruction::checkStyleSheet()
{
    // Prevent recursive loading of stylesheet.
    if (m_isHandlingBeforeLoad)
        return;

    if (m_target == "xml-stylesheet" && document().frame() && parentNode() == &document()) {
        // see http://www.w3.org/TR/xml-stylesheet/
        // ### support stylesheet included in a fragment of this (or another) document
        // ### make sure this gets called when adding from javascript
        bool attrsOk;
        const HashMap<String, String> attrs = parseAttributes(data(), attrsOk);
        if (!attrsOk)
            return;
        HashMap<String, String>::const_iterator i = attrs.find("type");
        String type;
        if (i != attrs.end())
            type = i->value;

        m_isCSS = type.isEmpty() || type == "text/css";
#if ENABLE(XSLT)
        m_isXSL = (type == "text/xml" || type == "text/xsl" || type == "application/xml" ||
                   type == "application/xhtml+xml" || type == "application/rss+xml" || type == "application/atom+xml");
        if (!m_isCSS && !m_isXSL)
#else
        if (!m_isCSS)
#endif
            return;

        String href = attrs.get("href");
        String alternate = attrs.get("alternate");
        m_alternate = alternate == "yes";
        m_title = attrs.get("title");
        m_media = attrs.get("media");

        if (m_alternate && m_title.isEmpty())
            return;

        if (href.length() > 1 && href[0] == '#') {
            m_localHref = href.substring(1);
#if ENABLE(XSLT)
            // We need to make a synthetic XSLStyleSheet that is embedded.  It needs to be able
            // to kick off import/include loads that can hang off some parent sheet.
            if (m_isXSL) {
                URL finalURL(ParsedURLString, m_localHref);
                m_sheet = XSLStyleSheet::createEmbedded(this, finalURL);
                m_loading = false;
            }
#endif
        } else {
            if (m_cachedSheet) {
                m_cachedSheet->removeClient(*this);
                m_cachedSheet = nullptr;
            }

            if (m_loading) {
                m_loading = false;
                document().styleScope().removePendingSheet(*this);
            }

            Ref<Document> originalDocument = document();

            String url = document().completeURL(href).string();

            {
            SetForScope<bool> change(m_isHandlingBeforeLoad, true);
            if (!dispatchBeforeLoadEvent(url))
                return;
            }

            bool didEventListenerDisconnectThisElement = !isConnected() || &document() != originalDocument.ptr();
            if (didEventListenerDisconnectThisElement)
                return;
            
            m_loading = true;
            document().styleScope().addPendingSheet(*this);

            ASSERT_WITH_SECURITY_IMPLICATION(!m_cachedSheet);

#if ENABLE(XSLT)
            if (m_isXSL) {
                auto options = CachedResourceLoader::defaultCachedResourceOptions();
                options.mode = FetchOptions::Mode::SameOrigin;
                m_cachedSheet = document().cachedResourceLoader().requestXSLStyleSheet({ResourceRequest(document().completeURL(href)), options});
            } else
#endif
            {
                String charset = attrs.get("charset");
                CachedResourceRequest request(document().completeURL(href), CachedResourceLoader::defaultCachedResourceOptions(), std::nullopt, charset.isEmpty() ? document().charset() : WTFMove(charset));

                m_cachedSheet = document().cachedResourceLoader().requestCSSStyleSheet(WTFMove(request));
            }
            if (m_cachedSheet)
                m_cachedSheet->addClient(*this);
            else {
                // The request may have been denied if (for example) the stylesheet is local and the document is remote.
                m_loading = false;
                document().styleScope().removePendingSheet(*this);
#if ENABLE(XSLT)
                if (m_isXSL)
                    document().styleScope().flushPendingUpdate();
#endif
            }
        }
    }
}

bool ProcessingInstruction::isLoading() const
{
    if (m_loading)
        return true;
    if (!m_sheet)
        return false;
    return m_sheet->isLoading();
}

bool ProcessingInstruction::sheetLoaded()
{
    if (!isLoading()) {
        if (document().styleScope().hasPendingSheet(*this))
            document().styleScope().removePendingSheet(*this);
#if ENABLE(XSLT)
        if (m_isXSL)
            document().styleScope().flushPendingUpdate();
#endif
        return true;
    }
    return false;
}

void ProcessingInstruction::setCSSStyleSheet(const String& href, const URL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet)
{
    if (!isConnected()) {
        ASSERT(!m_sheet);
        return;
    }

    ASSERT(m_isCSS);
    CSSParserContext parserContext(document(), baseURL, charset);

    auto cssSheet = CSSStyleSheet::create(StyleSheetContents::create(href, parserContext), *this);
    cssSheet.get().setDisabled(m_alternate);
    cssSheet.get().setTitle(m_title);
    cssSheet.get().setMediaQueries(MediaQuerySet::create(m_media));

    m_sheet = WTFMove(cssSheet);

    // We don't need the cross-origin security check here because we are
    // getting the sheet text in "strict" mode. This enforces a valid CSS MIME
    // type.
    Ref<Document> protect(document());
    parseStyleSheet(sheet->sheetText());
}

#if ENABLE(XSLT)
void ProcessingInstruction::setXSLStyleSheet(const String& href, const URL& baseURL, const String& sheet)
{
    ASSERT(m_isXSL);
    m_sheet = XSLStyleSheet::create(this, href, baseURL);
    Ref<Document> protect(document());
    parseStyleSheet(sheet);
}
#endif

void ProcessingInstruction::parseStyleSheet(const String& sheet)
{
    if (m_isCSS)
        downcast<CSSStyleSheet>(*m_sheet).contents().parseString(sheet);
#if ENABLE(XSLT)
    else if (m_isXSL)
        downcast<XSLStyleSheet>(*m_sheet).parseString(sheet);
#endif

    if (m_cachedSheet)
        m_cachedSheet->removeClient(*this);
    m_cachedSheet = nullptr;

    m_loading = false;

    if (m_isCSS)
        downcast<CSSStyleSheet>(*m_sheet).contents().checkLoaded();
#if ENABLE(XSLT)
    else if (m_isXSL)
        downcast<XSLStyleSheet>(*m_sheet).checkLoaded();
#endif
}

void ProcessingInstruction::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
{
    if (!sheet())
        return;
    
    addSubresourceURL(urls, sheet()->baseURL());
}

Node::InsertionNotificationRequest ProcessingInstruction::insertedInto(ContainerNode& insertionPoint)
{
    CharacterData::insertedInto(insertionPoint);
    if (!insertionPoint.isConnected())
        return InsertionDone;
    document().styleScope().addStyleSheetCandidateNode(*this, m_createdByParser);
    checkStyleSheet();
    return InsertionDone;
}

void ProcessingInstruction::removedFrom(ContainerNode& insertionPoint)
{
    CharacterData::removedFrom(insertionPoint);
    if (!insertionPoint.isConnected())
        return;
    
    document().styleScope().removeStyleSheetCandidateNode(*this);

    if (m_sheet) {
        ASSERT(m_sheet->ownerNode() == this);
        m_sheet->clearOwnerNode();
        m_sheet = nullptr;
    }

    if (m_loading) {
        m_loading = false;
        document().styleScope().removePendingSheet(*this);
    }

    document().styleScope().didChangeActiveStyleSheetCandidates();
}

void ProcessingInstruction::finishParsingChildren()
{
    m_createdByParser = false;
    CharacterData::finishParsingChildren();
}

} // namespace
