Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGAElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
4  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2010 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24
25 #include "core/svg/SVGAElement.h"
26
27 #include "core/SVGNames.h"
28 #include "core/XLinkNames.h"
29 #include "core/dom/Attr.h"
30 #include "core/dom/Attribute.h"
31 #include "core/dom/Document.h"
32 #include "core/events/KeyboardEvent.h"
33 #include "core/events/MouseEvent.h"
34 #include "core/frame/FrameHost.h"
35 #include "core/frame/LocalFrame.h"
36 #include "core/html/HTMLAnchorElement.h"
37 #include "core/html/HTMLFormElement.h"
38 #include "core/html/parser/HTMLParserIdioms.h"
39 #include "core/loader/FrameLoadRequest.h"
40 #include "core/loader/FrameLoader.h"
41 #include "core/loader/FrameLoaderTypes.h"
42 #include "core/page/Chrome.h"
43 #include "core/page/ChromeClient.h"
44 #include "core/page/Page.h"
45 #include "core/rendering/svg/RenderSVGInline.h"
46 #include "core/rendering/svg/RenderSVGText.h"
47 #include "core/rendering/svg/RenderSVGTransformableContainer.h"
48 #include "core/svg/animation/SVGSMILElement.h"
49 #include "platform/PlatformMouseEvent.h"
50 #include "platform/network/ResourceRequest.h"
51
52 namespace blink {
53
54 using namespace HTMLNames;
55
56 inline SVGAElement::SVGAElement(Document& document)
57     : SVGGraphicsElement(SVGNames::aTag, document)
58     , SVGURIReference(this)
59     , m_svgTarget(SVGAnimatedString::create(this, SVGNames::targetAttr, SVGString::create()))
60     , m_wasFocusedByMouse(false)
61 {
62     addToPropertyMap(m_svgTarget);
63 }
64
65 DEFINE_NODE_FACTORY(SVGAElement)
66
67 String SVGAElement::title() const
68 {
69     // If the xlink:title is set (non-empty string), use it.
70     const AtomicString& title = fastGetAttribute(XLinkNames::titleAttr);
71     if (!title.isEmpty())
72         return title;
73
74     // Otherwise, use the title of this element.
75     return SVGElement::title();
76 }
77
78 void SVGAElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
79 {
80     parseAttributeNew(name, value);
81 }
82
83 void SVGAElement::svgAttributeChanged(const QualifiedName& attrName)
84 {
85     // Unlike other SVG*Element classes, SVGAElement only listens to SVGURIReference changes
86     // as none of the other properties changes the linking behaviour for our <a> element.
87     if (SVGURIReference::isKnownAttribute(attrName)) {
88         SVGElement::InvalidationGuard invalidationGuard(this);
89
90         bool wasLink = isLink();
91         setIsLink(!hrefString().isNull());
92
93         if (wasLink != isLink())
94             setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::LinkColorChange));
95
96         return;
97     }
98
99     SVGGraphicsElement::svgAttributeChanged(attrName);
100 }
101
102 RenderObject* SVGAElement::createRenderer(RenderStyle*)
103 {
104     if (parentNode() && parentNode()->isSVGElement() && toSVGElement(parentNode())->isTextContent())
105         return new RenderSVGInline(this);
106
107     return new RenderSVGTransformableContainer(this);
108 }
109
110 void SVGAElement::defaultEventHandler(Event* event)
111 {
112     if (isLink()) {
113         ASSERT(event->target());
114         Node* target = event->target()->toNode();
115         ASSERT(target);
116         if ((focused() || target->focused()) && isEnterKeyKeypressEvent(event)) {
117             event->setDefaultHandled();
118             dispatchSimulatedClick(event);
119             return;
120         }
121
122         if (isLinkClick(event)) {
123             String url = stripLeadingAndTrailingHTMLSpaces(hrefString());
124
125             if (url[0] == '#') {
126                 Element* targetElement = treeScope().getElementById(AtomicString(url.substring(1)));
127                 if (targetElement && isSVGSMILElement(*targetElement)) {
128                     toSVGSMILElement(targetElement)->beginByLinkActivation();
129                     event->setDefaultHandled();
130                     return;
131                 }
132             }
133
134             AtomicString target(m_svgTarget->currentValue()->value());
135             if (target.isEmpty() && fastGetAttribute(XLinkNames::showAttr) == "new")
136                 target = AtomicString("_blank", AtomicString::ConstructFromLiteral);
137             event->setDefaultHandled();
138
139             LocalFrame* frame = document().frame();
140             if (!frame)
141                 return;
142             FrameLoadRequest frameRequest(&document(), ResourceRequest(document().completeURL(url)), target);
143             frameRequest.setTriggeringEvent(event);
144             frame->loader().load(frameRequest);
145             return;
146         }
147     }
148
149     SVGGraphicsElement::defaultEventHandler(event);
150 }
151
152 short SVGAElement::tabIndex() const
153 {
154     // Skip the supportsFocus check in SVGElement.
155     return Element::tabIndex();
156 }
157
158 bool SVGAElement::supportsFocus() const
159 {
160     if (hasEditableStyle())
161         return SVGGraphicsElement::supportsFocus();
162     // If not a link we should still be able to focus the element if it has tabIndex.
163     return isLink() || SVGGraphicsElement::supportsFocus();
164 }
165
166 bool SVGAElement::shouldHaveFocusAppearance() const
167 {
168     return !m_wasFocusedByMouse || SVGGraphicsElement::supportsFocus();
169 }
170
171 void SVGAElement::dispatchFocusEvent(Element* oldFocusedElement, FocusType type)
172 {
173     if (type != FocusTypePage)
174         m_wasFocusedByMouse = type == FocusTypeMouse;
175     SVGGraphicsElement::dispatchFocusEvent(oldFocusedElement, type);
176 }
177
178 bool SVGAElement::isURLAttribute(const Attribute& attribute) const
179 {
180     return attribute.name().localName() == hrefAttr || SVGGraphicsElement::isURLAttribute(attribute);
181 }
182
183 bool SVGAElement::isMouseFocusable() const
184 {
185     if (isLink())
186         return supportsFocus();
187
188     return SVGElement::isMouseFocusable();
189 }
190
191 bool SVGAElement::isKeyboardFocusable() const
192 {
193     if (isFocusable() && Element::supportsFocus())
194         return SVGElement::isKeyboardFocusable();
195
196     if (isLink())
197         return document().frameHost()->chrome().client().tabsToLinks();
198     return SVGElement::isKeyboardFocusable();
199 }
200
201 bool SVGAElement::canStartSelection() const
202 {
203     if (!isLink())
204         return SVGElement::canStartSelection();
205     return hasEditableStyle();
206 }
207
208 bool SVGAElement::willRespondToMouseClickEvents()
209 {
210     return isLink() || SVGGraphicsElement::willRespondToMouseClickEvents();
211 }
212
213 } // namespace blink