2e7d55fa67c7e16c98b3fc8a0acb45a186eb6528
[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 "SVGNames.h"
28 #include "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/events/ThreadLocalEventNames.h"
35 #include "core/frame/Frame.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/SVGElementInstance.h"
49 #include "core/svg/animation/SVGSMILElement.h"
50 #include "platform/PlatformMouseEvent.h"
51 #include "platform/network/ResourceRequest.h"
52
53 namespace WebCore {
54
55 using namespace HTMLNames;
56
57 // Animated property definitions
58 DEFINE_ANIMATED_STRING(SVGAElement, SVGNames::targetAttr, SVGTarget, svgTarget)
59 DEFINE_ANIMATED_STRING(SVGAElement, XLinkNames::hrefAttr, Href, href)
60
61 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGAElement)
62     REGISTER_LOCAL_ANIMATED_PROPERTY(svgTarget)
63     REGISTER_LOCAL_ANIMATED_PROPERTY(href)
64     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
65 END_REGISTER_ANIMATED_PROPERTIES
66
67 inline SVGAElement::SVGAElement(Document& document)
68     : SVGGraphicsElement(SVGNames::aTag, document)
69 {
70     ScriptWrappable::init(this);
71     registerAnimatedPropertiesForSVGAElement();
72 }
73
74 PassRefPtr<SVGAElement> SVGAElement::create(Document& document)
75 {
76     return adoptRef(new SVGAElement(document));
77 }
78
79 String SVGAElement::title() const
80 {
81     // If the xlink:title is set (non-empty string), use it.
82     const AtomicString& title = fastGetAttribute(XLinkNames::titleAttr);
83     if (!title.isEmpty())
84         return title;
85
86     // Otherwise, use the title of this element.
87     return SVGElement::title();
88 }
89
90 bool SVGAElement::isSupportedAttribute(const QualifiedName& attrName)
91 {
92     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
93     if (supportedAttributes.isEmpty()) {
94         SVGURIReference::addSupportedAttributes(supportedAttributes);
95         supportedAttributes.add(SVGNames::targetAttr);
96     }
97     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
98 }
99
100 void SVGAElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
101 {
102     if (!isSupportedAttribute(name)) {
103         SVGGraphicsElement::parseAttribute(name, value);
104         return;
105     }
106
107     if (name == SVGNames::targetAttr) {
108         setSVGTargetBaseValue(value);
109         return;
110     }
111
112     if (SVGURIReference::parseAttribute(name, value))
113         return;
114
115     ASSERT_NOT_REACHED();
116 }
117
118 void SVGAElement::svgAttributeChanged(const QualifiedName& attrName)
119 {
120     if (!isSupportedAttribute(attrName)) {
121         SVGGraphicsElement::svgAttributeChanged(attrName);
122         return;
123     }
124
125     SVGElementInstance::InvalidationGuard invalidationGuard(this);
126
127     // Unlike other SVG*Element classes, SVGAElement only listens to SVGURIReference changes
128     // as none of the other properties changes the linking behaviour for our <a> element.
129     if (SVGURIReference::isKnownAttribute(attrName)) {
130         bool wasLink = isLink();
131         setIsLink(!hrefCurrentValue().isNull());
132
133         if (wasLink != isLink())
134             setNeedsStyleRecalc();
135     }
136 }
137
138 RenderObject* SVGAElement::createRenderer(RenderStyle*)
139 {
140     if (parentNode() && parentNode()->isSVGElement() && toSVGElement(parentNode())->isTextContent())
141         return new RenderSVGInline(this);
142
143     return new RenderSVGTransformableContainer(this);
144 }
145
146 void SVGAElement::defaultEventHandler(Event* event)
147 {
148     if (isLink()) {
149         if (focused() && isEnterKeyKeydownEvent(event)) {
150             event->setDefaultHandled();
151             dispatchSimulatedClick(event);
152             return;
153         }
154
155         if (isLinkClick(event)) {
156             String url = stripLeadingAndTrailingHTMLSpaces(hrefCurrentValue());
157
158             if (url[0] == '#') {
159                 Element* targetElement = treeScope().getElementById(AtomicString(url.substring(1)));
160                 if (targetElement && isSVGSMILElement(*targetElement)) {
161                     toSVGSMILElement(targetElement)->beginByLinkActivation();
162                     event->setDefaultHandled();
163                     return;
164                 }
165                 // Only allow navigation to internal <view> anchors.
166                 if (targetElement && !targetElement->hasTagName(SVGNames::viewTag))
167                     return;
168             }
169
170             AtomicString target(svgTargetCurrentValue());
171             if (target.isEmpty() && fastGetAttribute(XLinkNames::showAttr) == "new")
172                 target = AtomicString("_blank", AtomicString::ConstructFromLiteral);
173             event->setDefaultHandled();
174
175             Frame* frame = document().frame();
176             if (!frame)
177                 return;
178             FrameLoadRequest frameRequest(&document(), ResourceRequest(document().completeURL(url)), target);
179             frameRequest.setTriggeringEvent(event);
180             frame->loader().load(frameRequest);
181             return;
182         }
183     }
184
185     SVGGraphicsElement::defaultEventHandler(event);
186 }
187
188 bool SVGAElement::supportsFocus() const
189 {
190     if (rendererIsEditable())
191         return SVGGraphicsElement::supportsFocus();
192     return true;
193 }
194
195 bool SVGAElement::rendererIsFocusable() const
196 {
197     if (renderer() && renderer()->absoluteClippedOverflowRect().isEmpty())
198         return false;
199
200     return SVGElement::rendererIsFocusable();
201 }
202
203 bool SVGAElement::isURLAttribute(const Attribute& attribute) const
204 {
205     return attribute.name().localName() == hrefAttr || SVGGraphicsElement::isURLAttribute(attribute);
206 }
207
208 bool SVGAElement::isMouseFocusable() const
209 {
210     return false;
211 }
212
213 bool SVGAElement::isKeyboardFocusable() const
214 {
215     if (!isFocusable())
216         return false;
217
218     if (Page* page = document().page())
219         return page->chrome().client().tabsToLinks();
220     return false;
221 }
222
223 bool SVGAElement::willRespondToMouseClickEvents()
224 {
225     return isLink() || SVGGraphicsElement::willRespondToMouseClickEvents();
226 }
227
228 } // namespace WebCore