/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Simon Hausmann <hausmann@kde.org>
 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
 *
 * 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 "core/html/HTMLAnchorElement.h"

#include "HTMLNames.h"
#include "core/dom/Attribute.h"
#include "core/editing/FrameSelection.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/MouseEvent.h"
#include "core/events/ThreadLocalEventNames.h"
#include "core/frame/Frame.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/FrameLoaderTypes.h"
#include "core/loader/PingLoader.h"
#include "core/page/Chrome.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/page/Settings.h"
#include "core/rendering/RenderImage.h"
#include "core/svg/graphics/SVGImage.h"
#include "platform/PlatformMouseEvent.h"
#include "platform/network/DNS.h"
#include "platform/network/ResourceRequest.h"
#include "public/platform/Platform.h"
#include "public/platform/WebPrescientNetworking.h"
#include "public/platform/WebURL.h"
#include "weborigin/KnownPorts.h"
#include "weborigin/SecurityOrigin.h"
#include "weborigin/SecurityPolicy.h"
#include "wtf/text/StringBuilder.h"

namespace WebCore {

namespace {

void preconnectToURL(const KURL& url, WebKit::WebPreconnectMotivation motivation)
{
    WebKit::WebPrescientNetworking* prescientNetworking = WebKit::Platform::current()->prescientNetworking();
    if (!prescientNetworking)
        return;

    prescientNetworking->preconnect(url, motivation);
}

}

class HTMLAnchorElement::PrefetchEventHandler {
public:
    static PassOwnPtr<PrefetchEventHandler> create(HTMLAnchorElement* anchorElement)
    {
        return adoptPtr(new HTMLAnchorElement::PrefetchEventHandler(anchorElement));
    }

    void reset();

    void handleEvent(Event* e);
    void didChangeHREF() { m_hadHREFChanged = true; }
    bool hasIssuedPreconnect() const { return m_hasIssuedPreconnect; }

private:
    explicit PrefetchEventHandler(HTMLAnchorElement*);

    void handleMouseOver(Event* event);
    void handleMouseOut(Event* event);
    void handleLeftMouseDown(Event* event);
    void handleGestureTapUnconfirmed(Event*);
    void handleGestureShowPress(Event*);
    void handleClick(Event* event);

    bool shouldPrefetch(const KURL&);
    void prefetch(WebKit::WebPreconnectMotivation);

    HTMLAnchorElement* m_anchorElement;
    double m_mouseOverTimestamp;
    double m_mouseDownTimestamp;
    double m_tapDownTimestamp;
    bool m_hadHREFChanged;
    bool m_hadTapUnconfirmed;
    bool m_hasIssuedPreconnect;
};

using namespace HTMLNames;

HTMLAnchorElement::HTMLAnchorElement(const QualifiedName& tagName, Document& document)
    : HTMLElement(tagName, document)
    , m_hasRootEditableElementForSelectionOnMouseDown(false)
    , m_wasShiftKeyDownOnMouseDown(false)
    , m_linkRelations(0)
    , m_cachedVisitedLinkHash(0)
{
    ScriptWrappable::init(this);
}

PassRefPtr<HTMLAnchorElement> HTMLAnchorElement::create(Document& document)
{
    return adoptRef(new HTMLAnchorElement(aTag, document));
}

PassRefPtr<HTMLAnchorElement> HTMLAnchorElement::create(const QualifiedName& tagName, Document& document)
{
    return adoptRef(new HTMLAnchorElement(tagName, document));
}

HTMLAnchorElement::~HTMLAnchorElement()
{
    clearRootEditableElementForSelectionOnMouseDown();
}

bool HTMLAnchorElement::supportsFocus() const
{
    if (rendererIsEditable())
        return HTMLElement::supportsFocus();
    // If not a link we should still be able to focus the element if it has tabIndex.
    return isLink() || HTMLElement::supportsFocus();
}

bool HTMLAnchorElement::isMouseFocusable() const
{
    // Links are focusable by default, but only allow links with tabindex or contenteditable to be mouse focusable.
    // https://bugs.webkit.org/show_bug.cgi?id=26856
    if (isLink())
        return HTMLElement::supportsFocus();

    return HTMLElement::isMouseFocusable();
}

bool HTMLAnchorElement::isKeyboardFocusable() const
{
    if (isFocusable() && Element::supportsFocus())
        return HTMLElement::isKeyboardFocusable();

    if (isLink()) {
        Page* page = document().page();
        if (!page)
            return false;
        if (!page->chrome().client().tabsToLinks())
            return false;
    }
    return HTMLElement::isKeyboardFocusable();
}

static void appendServerMapMousePosition(StringBuilder& url, Event* event)
{
    if (!event->isMouseEvent())
        return;

    ASSERT(event->target());
    Node* target = event->target()->toNode();
    ASSERT(target);
    if (!target->hasTagName(imgTag))
        return;

    HTMLImageElement* imageElement = toHTMLImageElement(event->target()->toNode());
    if (!imageElement || !imageElement->isServerMap())
        return;

    if (!imageElement->renderer() || !imageElement->renderer()->isRenderImage())
        return;
    RenderImage* renderer = toRenderImage(imageElement->renderer());

    // FIXME: This should probably pass true for useTransforms.
    FloatPoint absolutePosition = renderer->absoluteToLocal(FloatPoint(toMouseEvent(event)->pageX(), toMouseEvent(event)->pageY()));
    int x = absolutePosition.x();
    int y = absolutePosition.y();
    url.append('?');
    url.appendNumber(x);
    url.append(',');
    url.appendNumber(y);
}

void HTMLAnchorElement::defaultEventHandler(Event* event)
{
    if (isLink()) {
        if (focused() && isEnterKeyKeydownEvent(event) && treatLinkAsLiveForEventType(NonMouseEvent)) {
            event->setDefaultHandled();
            dispatchSimulatedClick(event);
            return;
        }

        prefetchEventHandler()->handleEvent(event);

        if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event))) {
            handleClick(event);
            prefetchEventHandler()->reset();
            return;
        }

        if (rendererIsEditable()) {
            // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked
            // for the LiveWhenNotFocused editable link behavior
            if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() != RightButton && document().frame()) {
                setRootEditableElementForSelectionOnMouseDown(document().frame()->selection().rootEditableElement());
                m_wasShiftKeyDownOnMouseDown = toMouseEvent(event)->shiftKey();
            } else if (event->type() == EventTypeNames::mouseover) {
                // These are cleared on mouseover and not mouseout because their values are needed for drag events,
                // but drag events happen after mouse out events.
                clearRootEditableElementForSelectionOnMouseDown();
                m_wasShiftKeyDownOnMouseDown = false;
            }
        }
    }

    HTMLElement::defaultEventHandler(event);
}

void HTMLAnchorElement::setActive(bool down, bool pause)
{
    if (rendererIsEditable()) {
        EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior;
        if (Settings* settings = document().settings())
            editableLinkBehavior = settings->editableLinkBehavior();

        switch (editableLinkBehavior) {
            default:
            case EditableLinkDefaultBehavior:
            case EditableLinkAlwaysLive:
                break;

            case EditableLinkNeverLive:
                return;

            // Don't set the link to be active if the current selection is in the same editable block as
            // this link
            case EditableLinkLiveWhenNotFocused:
                if (down && document().frame() && document().frame()->selection().rootEditableElement() == rootEditableElement())
                    return;
                break;

            case EditableLinkOnlyLiveWithShiftKey:
                return;
        }

    }

    ContainerNode::setActive(down, pause);
}

void HTMLAnchorElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    if (name == hrefAttr) {
        bool wasLink = isLink();
        setIsLink(!value.isNull());
        if (wasLink != isLink()) {
            didAffectSelector(AffectedSelectorLink | AffectedSelectorVisited | AffectedSelectorEnabled);
            if (wasLink && treeScope().adjustedFocusedElement() == this) {
                // We might want to call blur(), but it's dangerous to dispatch
                // events here.
                document().setNeedsFocusedElementCheck();
            }
        }
        if (isLink()) {
            String parsedURL = stripLeadingAndTrailingHTMLSpaces(value);
            if (document().isDNSPrefetchEnabled()) {
                if (protocolIs(parsedURL, "http") || protocolIs(parsedURL, "https") || parsedURL.startsWith("//"))
                    prefetchDNS(document().completeURL(parsedURL).host());
            }

            if (wasLink)
                prefetchEventHandler()->didChangeHREF();
        }
        invalidateCachedVisitedLinkHash();
    } else if (name == nameAttr || name == titleAttr) {
        // Do nothing.
    } else if (name == relAttr)
        setRel(value);
    else
        HTMLElement::parseAttribute(name, value);
}

void HTMLAnchorElement::accessKeyAction(bool sendMouseEvents)
{
    dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}

bool HTMLAnchorElement::isURLAttribute(const Attribute& attribute) const
{
    return attribute.name().localName() == hrefAttr || HTMLElement::isURLAttribute(attribute);
}

bool HTMLAnchorElement::canStartSelection() const
{
    // FIXME: We probably want this same behavior in SVGAElement too
    if (!isLink())
        return HTMLElement::canStartSelection();
    return rendererIsEditable();
}

bool HTMLAnchorElement::draggable() const
{
    // Should be draggable if we have an href attribute.
    const AtomicString& value = getAttribute(draggableAttr);
    if (equalIgnoringCase(value, "true"))
        return true;
    if (equalIgnoringCase(value, "false"))
        return false;
    return hasAttribute(hrefAttr);
}

KURL HTMLAnchorElement::href() const
{
    return document().completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(hrefAttr)));
}

void HTMLAnchorElement::setHref(const AtomicString& value)
{
    setAttribute(hrefAttr, value);
}

KURL HTMLAnchorElement::url() const
{
    return href();
}

void HTMLAnchorElement::setURL(const KURL& url)
{
    setHref(url.string());
}

String HTMLAnchorElement::input() const
{
    return getAttribute(hrefAttr);
}

void HTMLAnchorElement::setInput(const String& value)
{
    setHref(value);
}

bool HTMLAnchorElement::hasRel(uint32_t relation) const
{
    return m_linkRelations & relation;
}

void HTMLAnchorElement::setRel(const String& value)
{
    m_linkRelations = 0;
    SpaceSplitString newLinkRelations(value, true);
    // FIXME: Add link relations as they are implemented
    if (newLinkRelations.contains("noreferrer"))
        m_linkRelations |= RelationNoReferrer;
}

const AtomicString& HTMLAnchorElement::name() const
{
    return getNameAttribute();
}

short HTMLAnchorElement::tabIndex() const
{
    // Skip the supportsFocus check in HTMLElement.
    return Element::tabIndex();
}

String HTMLAnchorElement::target() const
{
    return getAttribute(targetAttr);
}


String HTMLAnchorElement::text()
{
    return innerText();
}

bool HTMLAnchorElement::isLiveLink() const
{
    return isLink() && treatLinkAsLiveForEventType(m_wasShiftKeyDownOnMouseDown ? MouseEventWithShiftKey : MouseEventWithoutShiftKey);
}

void HTMLAnchorElement::sendPings(const KURL& destinationURL)
{
    if (!hasAttribute(pingAttr) || !document().settings() || !document().settings()->hyperlinkAuditingEnabled())
        return;

    SpaceSplitString pingURLs(getAttribute(pingAttr), false);
    for (unsigned i = 0; i < pingURLs.size(); i++)
        PingLoader::sendPing(document().frame(), document().completeURL(pingURLs[i]), destinationURL);
}

void HTMLAnchorElement::handleClick(Event* event)
{
    event->setDefaultHandled();

    Frame* frame = document().frame();
    if (!frame)
        return;

    StringBuilder url;
    url.append(stripLeadingAndTrailingHTMLSpaces(fastGetAttribute(hrefAttr)));
    appendServerMapMousePosition(url, event);
    KURL completedURL = document().completeURL(url.toString());

    // Schedule the ping before the frame load. Prerender in Chrome may kill the renderer as soon as the navigation is
    // sent out.
    sendPings(completedURL);

    ResourceRequest request(completedURL);
    if (prefetchEventHandler()->hasIssuedPreconnect())
        frame->loader().client()->dispatchWillRequestAfterPreconnect(request);
    if (hasAttribute(downloadAttr)) {
        if (!hasRel(RelationNoReferrer)) {
            String referrer = SecurityPolicy::generateReferrerHeader(document().referrerPolicy(), completedURL, frame->loader().outgoingReferrer());
            if (!referrer.isEmpty())
                request.setHTTPReferrer(referrer);
        }

        frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, fastGetAttribute(downloadAttr));
    } else {
        FrameLoadRequest frameRequest(document().securityOrigin(), request, target());
        frameRequest.setTriggeringEvent(event);
        if (hasRel(RelationNoReferrer))
            frameRequest.setShouldSendReferrer(NeverSendReferrer);
        frame->loader().load(frameRequest);
    }
}

HTMLAnchorElement::EventType HTMLAnchorElement::eventType(Event* event)
{
    if (!event->isMouseEvent())
        return NonMouseEvent;
    return toMouseEvent(event)->shiftKey() ? MouseEventWithShiftKey : MouseEventWithoutShiftKey;
}

bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const
{
    if (!rendererIsEditable())
        return true;

    Settings* settings = document().settings();
    if (!settings)
        return true;

    switch (settings->editableLinkBehavior()) {
    case EditableLinkDefaultBehavior:
    case EditableLinkAlwaysLive:
        return true;

    case EditableLinkNeverLive:
        return false;

    // If the selection prior to clicking on this link resided in the same editable block as this link,
    // and the shift key isn't pressed, we don't want to follow the link.
    case EditableLinkLiveWhenNotFocused:
        return eventType == MouseEventWithShiftKey || (eventType == MouseEventWithoutShiftKey && rootEditableElementForSelectionOnMouseDown() != rootEditableElement());

    case EditableLinkOnlyLiveWithShiftKey:
        return eventType == MouseEventWithShiftKey;
    }

    ASSERT_NOT_REACHED();
    return false;
}

bool isEnterKeyKeydownEvent(Event* event)
{
    return event->type() == EventTypeNames::keydown && event->isKeyboardEvent() && toKeyboardEvent(event)->keyIdentifier() == "Enter";
}

bool isLinkClick(Event* event)
{
    return event->type() == EventTypeNames::click && (!event->isMouseEvent() || toMouseEvent(event)->button() != RightButton);
}

bool HTMLAnchorElement::willRespondToMouseClickEvents()
{
    return isLink() || HTMLElement::willRespondToMouseClickEvents();
}

typedef HashMap<const HTMLAnchorElement*, RefPtr<Element> > RootEditableElementMap;

static RootEditableElementMap& rootEditableElementMap()
{
    DEFINE_STATIC_LOCAL(RootEditableElementMap, map, ());
    return map;
}

Element* HTMLAnchorElement::rootEditableElementForSelectionOnMouseDown() const
{
    if (!m_hasRootEditableElementForSelectionOnMouseDown)
        return 0;
    return rootEditableElementMap().get(this);
}

void HTMLAnchorElement::clearRootEditableElementForSelectionOnMouseDown()
{
    if (!m_hasRootEditableElementForSelectionOnMouseDown)
        return;
    rootEditableElementMap().remove(this);
    m_hasRootEditableElementForSelectionOnMouseDown = false;
}

void HTMLAnchorElement::setRootEditableElementForSelectionOnMouseDown(Element* element)
{
    if (!element) {
        clearRootEditableElementForSelectionOnMouseDown();
        return;
    }

    rootEditableElementMap().set(this, element);
    m_hasRootEditableElementForSelectionOnMouseDown = true;
}

HTMLAnchorElement::PrefetchEventHandler* HTMLAnchorElement::prefetchEventHandler()
{
    if (!m_prefetchEventHandler)
        m_prefetchEventHandler = PrefetchEventHandler::create(this);

    return m_prefetchEventHandler.get();
}

HTMLAnchorElement::PrefetchEventHandler::PrefetchEventHandler(HTMLAnchorElement* anchorElement)
    : m_anchorElement(anchorElement)
{
    ASSERT(m_anchorElement);

    reset();
}

void HTMLAnchorElement::PrefetchEventHandler::reset()
{
    m_hadHREFChanged = false;
    m_mouseOverTimestamp = 0;
    m_mouseDownTimestamp = 0;
    m_hadTapUnconfirmed = false;
    m_tapDownTimestamp = 0;
    m_hasIssuedPreconnect = false;
}

void HTMLAnchorElement::PrefetchEventHandler::handleEvent(Event* event)
{
    if (!shouldPrefetch(m_anchorElement->href()))
        return;

    if (event->type() == EventTypeNames::mouseover)
        handleMouseOver(event);
    else if (event->type() == EventTypeNames::mouseout)
        handleMouseOut(event);
    else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton)
        handleLeftMouseDown(event);
    else if (event->type() == EventTypeNames::gestureshowpress)
        handleGestureShowPress(event);
    else if (event->type() == EventTypeNames::gesturetapunconfirmed)
        handleGestureTapUnconfirmed(event);
    else if (isLinkClick(event))
        handleClick(event);
}

void HTMLAnchorElement::PrefetchEventHandler::handleMouseOver(Event* event)
{
    if (m_mouseOverTimestamp == 0.0) {
        m_mouseOverTimestamp = event->timeStamp();

        WebKit::Platform::current()->histogramEnumeration("MouseEventPrefetch.MouseOvers", 0, 2);

        prefetch(WebKit::WebPreconnectMotivationLinkMouseOver);
    }
}

void HTMLAnchorElement::PrefetchEventHandler::handleMouseOut(Event* event)
{
    if (m_mouseOverTimestamp > 0.0) {
        double mouseOverDuration = convertDOMTimeStampToSeconds(event->timeStamp() - m_mouseOverTimestamp);
        WebKit::Platform::current()->histogramCustomCounts("MouseEventPrefetch.MouseOverDuration_NoClick", mouseOverDuration * 1000, 0, 10000, 100);

        m_mouseOverTimestamp = 0.0;
    }
}

void HTMLAnchorElement::PrefetchEventHandler::handleLeftMouseDown(Event* event)
{
    m_mouseDownTimestamp = event->timeStamp();

    WebKit::Platform::current()->histogramEnumeration("MouseEventPrefetch.MouseDowns", 0, 2);

    prefetch(WebKit::WebPreconnectMotivationLinkMouseDown);
}

void HTMLAnchorElement::PrefetchEventHandler::handleGestureTapUnconfirmed(Event* event)
{
    m_hadTapUnconfirmed = true;

    WebKit::Platform::current()->histogramEnumeration("MouseEventPrefetch.TapUnconfirmeds", 0, 2);

    prefetch(WebKit::WebPreconnectMotivationLinkTapUnconfirmed);
}

void HTMLAnchorElement::PrefetchEventHandler::handleGestureShowPress(Event* event)
{
    m_tapDownTimestamp = event->timeStamp();

    WebKit::Platform::current()->histogramEnumeration("MouseEventPrefetch.TapDowns", 0, 2);

    prefetch(WebKit::WebPreconnectMotivationLinkTapDown);
}

void HTMLAnchorElement::PrefetchEventHandler::handleClick(Event* event)
{
    bool capturedMouseOver = (m_mouseOverTimestamp > 0.0);
    if (capturedMouseOver) {
        double mouseOverDuration = convertDOMTimeStampToSeconds(event->timeStamp() - m_mouseOverTimestamp);

        WebKit::Platform::current()->histogramCustomCounts("MouseEventPrefetch.MouseOverDuration_Click", mouseOverDuration * 1000, 0, 10000, 100);
    }

    bool capturedMouseDown = (m_mouseDownTimestamp > 0.0);
    WebKit::Platform::current()->histogramEnumeration("MouseEventPrefetch.MouseDownFollowedByClick", capturedMouseDown, 2);

    if (capturedMouseDown) {
        double mouseDownDuration = convertDOMTimeStampToSeconds(event->timeStamp() - m_mouseDownTimestamp);

        WebKit::Platform::current()->histogramCustomCounts("MouseEventPrefetch.MouseDownDuration_Click", mouseDownDuration * 1000, 0, 10000, 100);
    }

    bool capturedTapDown = (m_tapDownTimestamp > 0.0);
    if (capturedTapDown) {
        double tapDownDuration = convertDOMTimeStampToSeconds(event->timeStamp() - m_tapDownTimestamp);

        WebKit::Platform::current()->histogramCustomCounts("MouseEventPrefetch.TapDownDuration_Click", tapDownDuration * 1000, 0, 10000, 100);
    }

    int flags = (m_hadTapUnconfirmed ? 2 : 0) | (capturedTapDown ? 1 : 0);
    WebKit::Platform::current()->histogramEnumeration("MouseEventPrefetch.PreTapEventsFollowedByClick", flags, 4);
}

bool HTMLAnchorElement::PrefetchEventHandler::shouldPrefetch(const KURL& url)
{
    if (m_hadHREFChanged)
        return false;

    if (m_anchorElement->hasEventListeners(EventTypeNames::click))
        return false;

    if (!url.protocolIsInHTTPFamily())
        return false;

    Document& document = m_anchorElement->document();

    if (!document.securityOrigin()->canDisplay(url))
        return false;

    if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(document.url(), url))
        return false;

    Frame* frame = document.frame();
    if (!frame)
        return false;

    // Links which create new window/tab are avoided because they may require user approval interaction.
    if (!m_anchorElement->target().isEmpty())
        return false;

    return true;
}

void HTMLAnchorElement::PrefetchEventHandler::prefetch(WebKit::WebPreconnectMotivation motivation)
{
    const KURL& url = m_anchorElement->href();

    if (!shouldPrefetch(url))
        return;

    // The precision of current MouseOver trigger is too low to actually trigger preconnects.
    if (motivation == WebKit::WebPreconnectMotivationLinkMouseOver)
        return;

    preconnectToURL(url, motivation);
    m_hasIssuedPreconnect = true;
}

bool HTMLAnchorElement::isInteractiveContent() const
{
    return true;
}

}
