/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
 *
 * 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 "ScriptElement.h"

#include "CachedScript.h"
#include "DocLoader.h"
#include "Document.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLNames.h"
#include "HTMLScriptElement.h"
#include "MIMETypeRegistry.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "StringHash.h"
#include "Text.h"
#include <wtf/StdLibExtras.h>

#if ENABLE(SVG)
#include "SVGNames.h"
#include "SVGScriptElement.h"
#endif

namespace WebCore {

void ScriptElement::insertedIntoDocument(ScriptElementData& data, const String& sourceUrl)
{
    if (data.createdByParser())
        return;

    if (!sourceUrl.isEmpty()) {
        data.requestScript(sourceUrl);
        return;
    }

    // If there's an empty script node, we shouldn't evaluate the script
    // because if a script is inserted afterwards (by setting text or innerText)
    // it should be evaluated, and evaluateScript only evaluates a script once.
    data.evaluateScript(ScriptSourceCode(data.scriptContent(), data.element()->document()->url())); // FIXME: Provide a real starting line number here.
}

void ScriptElement::removedFromDocument(ScriptElementData& data)
{
    // Eventually stop loading any not-yet-finished content
    data.stopLoadRequest();
}

void ScriptElement::childrenChanged(ScriptElementData& data)
{
    if (data.createdByParser())
        return;

    Element* element = data.element();

    // If a node is inserted as a child of the script element
    // and the script element has been inserted in the document
    // we evaluate the script.
    if (element->inDocument() && element->firstChild())
        data.evaluateScript(ScriptSourceCode(data.scriptContent(), element->document()->url())); // FIXME: Provide a real starting line number here
}

void ScriptElement::finishParsingChildren(ScriptElementData& data, const String& sourceUrl)
{
    // The parser just reached </script>. If we have no src and no text,
    // allow dynamic loading later.
    if (sourceUrl.isEmpty() && data.scriptContent().isEmpty())
        data.setCreatedByParser(false);
}

void ScriptElement::handleSourceAttribute(ScriptElementData& data, const String& sourceUrl)
{
    if (data.ignoresLoadRequest() || sourceUrl.isEmpty())
        return;

    data.requestScript(sourceUrl);
}

// Helper function
static bool isSupportedJavaScriptLanguage(const String& language)
{
    typedef HashSet<String, CaseFoldingHash> LanguageSet;
    DEFINE_STATIC_LOCAL(LanguageSet, languages, ());
    if (languages.isEmpty()) {
        languages.add("javascript");
        languages.add("javascript");
        languages.add("javascript1.0");
        languages.add("javascript1.1");
        languages.add("javascript1.2");
        languages.add("javascript1.3");
        languages.add("javascript1.4");
        languages.add("javascript1.5");
        languages.add("javascript1.6");
        languages.add("javascript1.7");
        languages.add("livescript");
        languages.add("ecmascript");
        languages.add("jscript");                
    }

    return languages.contains(language);
}

// ScriptElementData
ScriptElementData::ScriptElementData(ScriptElement* scriptElement, Element* element)
    : m_scriptElement(scriptElement)
    , m_element(element)
    , m_cachedScript(0)
    , m_createdByParser(false)
    , m_requested(false)
    , m_evaluated(false)
    , m_firedLoad(false)
{
    ASSERT(m_scriptElement);
    ASSERT(m_element);
}

ScriptElementData::~ScriptElementData()
{
    stopLoadRequest();
}

void ScriptElementData::requestScript(const String& sourceUrl)
{
    Document* document = m_element->document();

    // FIXME: Eventually we'd like to evaluate scripts which are inserted into a 
    // viewless document but this'll do for now.
    // See http://bugs.webkit.org/show_bug.cgi?id=5727
    if (!document->frame())
        return;

    if (!m_element->dispatchBeforeLoadEvent(sourceUrl))
        return;

    ASSERT(!m_cachedScript);
    m_cachedScript = document->docLoader()->requestScript(sourceUrl, scriptCharset());
    m_requested = true;

    // m_createdByParser is never reset - always resied at the initial value set while parsing.
    // m_evaluated is left untouched as well to avoid script reexecution, if a <script> element
    // is removed and reappended to the document.
    m_firedLoad = false;

    if (m_cachedScript) {
        m_cachedScript->addClient(this);
        return;
    }

    m_scriptElement->dispatchErrorEvent();
}

void ScriptElementData::evaluateScript(const ScriptSourceCode& sourceCode)
{
    if (m_evaluated || sourceCode.isEmpty() || !shouldExecuteAsJavaScript())
        return;

    if (Frame* frame = m_element->document()->frame()) {
        if (!frame->script()->canExecuteScripts(AboutToExecuteScript))
            return;

        m_evaluated = true;

        frame->script()->evaluate(sourceCode);
        Document::updateStyleForAllDocuments();
    }
}

void ScriptElementData::stopLoadRequest()
{
    if (m_cachedScript) {
        m_cachedScript->removeClient(this);
        m_cachedScript = 0;
    }
}

void ScriptElementData::execute(CachedScript* cachedScript)
{
    ASSERT(cachedScript);
    if (cachedScript->errorOccurred())
        m_scriptElement->dispatchErrorEvent();
    else {
        evaluateScript(ScriptSourceCode(cachedScript));
        m_scriptElement->dispatchLoadEvent();
    }
    cachedScript->removeClient(this);
}

void ScriptElementData::notifyFinished(CachedResource* o)
{
    ASSERT_UNUSED(o, o == m_cachedScript);
    m_element->document()->executeScriptSoon(this, m_cachedScript);
    m_cachedScript = 0;
}

bool ScriptElementData::ignoresLoadRequest() const
{
    return m_evaluated || m_requested || m_createdByParser || !m_element->inDocument();
}

bool ScriptElementData::shouldExecuteAsJavaScript() const
{
    /*
         Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3.
         Mozilla 1.8 and WinIE 7 both accept javascript and livescript.
         WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't.
         Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace.
         We want to accept all the values that either of these browsers accept, but not other values.
     */
    String type = m_scriptElement->typeAttributeValue();
    if (!type.isEmpty()) {
        if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower()))
            return false;
    } else {
        String language = m_scriptElement->languageAttributeValue();
        if (!language.isEmpty() && !isSupportedJavaScriptLanguage(language))
            return false;
    }    

    // No type or language is specified, so we assume the script to be JavaScript.
    // We don't yet support setting event listeners via the 'for' attribute for scripts.
    // If there is such an attribute it's likely better to not execute the script than to do so
    // immediately and unconditionally.
    // FIXME: After <rdar://problem/4471751> / https://bugs.webkit.org/show_bug.cgi?id=16915 are resolved 
    // and we support the for syntax in script tags, this check can be removed and we should just
    // return 'true' here.
    String forAttribute = m_scriptElement->forAttributeValue();
    String eventAttribute = m_scriptElement->eventAttributeValue();
    if (forAttribute.isEmpty() || eventAttribute.isEmpty())
        return true;
    
    forAttribute = forAttribute.stripWhiteSpace();
    eventAttribute = eventAttribute.stripWhiteSpace();
    return equalIgnoringCase(forAttribute, "window") && (equalIgnoringCase(eventAttribute, "onload") || equalIgnoringCase(eventAttribute, "onload()"));
}

String ScriptElementData::scriptCharset() const
{
    // First we try to get encoding from charset attribute.
    String charset = m_scriptElement->charsetAttributeValue().stripWhiteSpace();

    // If charset has not been declared in script tag, fall back to frame encoding.
    if (charset.isEmpty()) {
        if (Frame* frame = m_element->document()->frame())
            charset = frame->loader()->writer()->encoding();
    }

    return charset;
}

String ScriptElementData::scriptContent() const
{
    Vector<UChar> val;
    Text* firstTextNode = 0;
    bool foundMultipleTextNodes = false;

    for (Node* n = m_element->firstChild(); n; n = n->nextSibling()) {
        if (!n->isTextNode())
            continue;

        Text* t = static_cast<Text*>(n);
        if (foundMultipleTextNodes)
            append(val, t->data());
        else if (firstTextNode) {
            append(val, firstTextNode->data());
            append(val, t->data());
            foundMultipleTextNodes = true;
        } else
            firstTextNode = t;
    }

    if (firstTextNode && !foundMultipleTextNodes)
        return firstTextNode->data();

    return String::adopt(val);
}

ScriptElement* toScriptElement(Element* element)
{
    if (element->isHTMLElement() && element->hasTagName(HTMLNames::scriptTag))
        return static_cast<HTMLScriptElement*>(element);

#if ENABLE(SVG)
    if (element->isSVGElement() && element->hasTagName(SVGNames::scriptTag))
        return static_cast<SVGScriptElement*>(element);
#endif

    return 0;
}

}
