Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLAnchorElement.cpp
index 47990fa..633b316 100644 (file)
 #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/frame/FrameHost.h"
+#include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
+#include "core/frame/UseCounter.h"
 #include "core/html/HTMLFormElement.h"
 #include "core/html/HTMLImageElement.h"
 #include "core/html/parser/HTMLParserIdioms.h"
@@ -109,27 +109,19 @@ 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)
+PassRefPtrWillBeRawPtr<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));
+    return adoptRefWillBeRefCountedGarbageCollected(new HTMLAnchorElement(aTag, document));
 }
 
 HTMLAnchorElement::~HTMLAnchorElement()
 {
-    clearRootEditableElementForSelectionOnMouseDown();
 }
 
 bool HTMLAnchorElement::supportsFocus() const
@@ -170,16 +162,16 @@ static void appendServerMapMousePosition(StringBuilder& url, Event* event)
     ASSERT(event->target());
     Node* target = event->target()->toNode();
     ASSERT(target);
-    if (!target->hasTagName(imgTag))
+    if (!isHTMLImageElement(*target))
         return;
 
-    HTMLImageElement* imageElement = toHTMLImageElement(event->target()->toNode());
-    if (!imageElement || !imageElement->isServerMap())
+    HTMLImageElement& imageElement = toHTMLImageElement(*target);
+    if (!imageElement.isServerMap())
         return;
 
-    if (!imageElement->renderer() || !imageElement->renderer()->isRenderImage())
+    if (!imageElement.renderer() || !imageElement.renderer()->isRenderImage())
         return;
-    RenderImage* renderer = toRenderImage(imageElement->renderer());
+    RenderImage* renderer = toRenderImage(imageElement.renderer());
 
     // FIXME: This should probably pass true for useTransforms.
     FloatPoint absolutePosition = renderer->absoluteToLocal(FloatPoint(toMouseEvent(event)->pageX(), toMouseEvent(event)->pageY()));
@@ -194,7 +186,7 @@ static void appendServerMapMousePosition(StringBuilder& url, Event* event)
 void HTMLAnchorElement::defaultEventHandler(Event* event)
 {
     if (isLink()) {
-        if (focused() && isEnterKeyKeydownEvent(event) && treatLinkAsLiveForEventType(NonMouseEvent)) {
+        if (focused() && isEnterKeyKeydownEvent(event) && isLiveLink()) {
             event->setDefaultHandled();
             dispatchSimulatedClick(event);
             return;
@@ -202,25 +194,11 @@ void HTMLAnchorElement::defaultEventHandler(Event* event)
 
         prefetchEventHandler()->handleEvent(event);
 
-        if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event))) {
+        if (isLinkClick(event) && isLiveLink()) {
             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);
@@ -228,32 +206,8 @@ void HTMLAnchorElement::defaultEventHandler(Event* event)
 
 void HTMLAnchorElement::setActive(bool down)
 {
-    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;
-        }
-
-    }
+    if (rendererIsEditable())
+        return;
 
     ContainerNode::setActive(down);
 }
@@ -300,9 +254,13 @@ bool HTMLAnchorElement::isURLAttribute(const Attribute& attribute) const
     return attribute.name().localName() == hrefAttr || HTMLElement::isURLAttribute(attribute);
 }
 
+bool HTMLAnchorElement::hasLegalLinkAttribute(const QualifiedName& name) const
+{
+    return name == hrefAttr || HTMLElement::hasLegalLinkAttribute(name);
+}
+
 bool HTMLAnchorElement::canStartSelection() const
 {
-    // FIXME: We probably want this same behavior in SVGAElement too
     if (!isLink())
         return HTMLElement::canStartSelection();
     return rendererIsEditable();
@@ -379,23 +337,20 @@ AtomicString HTMLAnchorElement::target() const
     return getAttribute(targetAttr);
 }
 
-
-String HTMLAnchorElement::text()
-{
-    return innerText();
-}
-
 bool HTMLAnchorElement::isLiveLink() const
 {
-    return isLink() && treatLinkAsLiveForEventType(m_wasShiftKeyDownOnMouseDown ? MouseEventWithShiftKey : MouseEventWithoutShiftKey);
+    return isLink() && !rendererIsEditable();
 }
 
 void HTMLAnchorElement::sendPings(const KURL& destinationURL)
 {
-    if (!hasAttribute(pingAttr) || !document().settings() || !document().settings()->hyperlinkAuditingEnabled())
+    const AtomicString& pingValue = getAttribute(pingAttr);
+    if (pingValue.isNull() || !document().settings() || !document().settings()->hyperlinkAuditingEnabled())
         return;
 
-    SpaceSplitString pingURLs(getAttribute(pingAttr), false);
+    UseCounter::count(document(), UseCounter::HTMLAnchorElementPingAttribute);
+
+    SpaceSplitString pingURLs(pingValue, false);
     for (unsigned i = 0; i < pingURLs.size(); i++)
         PingLoader::sendPing(document().frame(), document().completeURL(pingURLs[i]), destinationURL);
 }
@@ -404,7 +359,7 @@ void HTMLAnchorElement::handleClick(Event* event)
 {
     event->setDefaultHandled();
 
-    Frame* frame = document().frame();
+    LocalFrame* frame = document().frame();
     if (!frame)
         return;
 
@@ -427,7 +382,10 @@ void HTMLAnchorElement::handleClick(Event* event)
                 request.setHTTPReferrer(Referrer(referrer, document().referrerPolicy()));
         }
 
-        frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, fastGetAttribute(downloadAttr));
+        bool isSameOrigin = document().securityOrigin()->canRequest(completedURL);
+        const AtomicString& suggestedName = (isSameOrigin ? fastGetAttribute(downloadAttr) : nullAtom);
+
+        frame->loader().client()->loadURLExternally(request, NavigationPolicyDownload, suggestedName);
     } else {
         FrameLoadRequest frameRequest(&document(), request, target());
         frameRequest.setTriggeringEvent(event);
@@ -437,43 +395,6 @@ void HTMLAnchorElement::handleClick(Event* event)
     }
 }
 
-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";
@@ -489,40 +410,6 @@ 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)
@@ -664,7 +551,7 @@ bool HTMLAnchorElement::PrefetchEventHandler::shouldPrefetch(const KURL& url)
     if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(document.url(), url))
         return false;
 
-    Frame* frame = document.frame();
+    LocalFrame* frame = document.frame();
     if (!frame)
         return false;