Upstream version 9.38.198.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 {
61     ScriptWrappable::init(this);
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);
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         if (focused() && isEnterKeyKeydownEvent(event)) {
114             event->setDefaultHandled();
115             dispatchSimulatedClick(event);
116             return;
117         }
118
119         if (isLinkClick(event)) {
120             String url = stripLeadingAndTrailingHTMLSpaces(hrefString());
121
122             if (url[0] == '#') {
123                 Element* targetElement = treeScope().getElementById(AtomicString(url.substring(1)));
124                 if (targetElement && isSVGSMILElement(*targetElement)) {
125                     toSVGSMILElement(targetElement)->beginByLinkActivation();
126                     event->setDefaultHandled();
127                     return;
128                 }
129             }
130
131             AtomicString target(m_svgTarget->currentValue()->value());
132             if (target.isEmpty() && fastGetAttribute(XLinkNames::showAttr) == "new")
133                 target = AtomicString("_blank", AtomicString::ConstructFromLiteral);
134             event->setDefaultHandled();
135
136             LocalFrame* frame = document().frame();
137             if (!frame)
138                 return;
139             FrameLoadRequest frameRequest(&document(), ResourceRequest(document().completeURL(url)), target);
140             frameRequest.setTriggeringEvent(event);
141             frame->loader().load(frameRequest);
142             return;
143         }
144     }
145
146     SVGGraphicsElement::defaultEventHandler(event);
147 }
148
149 short SVGAElement::tabIndex() const
150 {
151     // Skip the supportsFocus check in SVGElement.
152     return Element::tabIndex();
153 }
154
155 bool SVGAElement::supportsFocus() const
156 {
157     if (hasEditableStyle())
158         return SVGGraphicsElement::supportsFocus();
159     // If not a link we should still be able to focus the element if it has tabIndex.
160     return isLink() || Element::supportsFocus();
161 }
162
163 bool SVGAElement::isURLAttribute(const Attribute& attribute) const
164 {
165     return attribute.name().localName() == hrefAttr || SVGGraphicsElement::isURLAttribute(attribute);
166 }
167
168 bool SVGAElement::isMouseFocusable() const
169 {
170     // Links are focusable by default, but only allow links with tabindex or contenteditable to be mouse focusable.
171     // https://bugs.webkit.org/show_bug.cgi?id=26856
172     if (isLink())
173         return Element::supportsFocus();
174
175     return SVGElement::isMouseFocusable();
176 }
177
178 bool SVGAElement::isKeyboardFocusable() const
179 {
180     if (isFocusable() && Element::supportsFocus())
181         return SVGElement::isKeyboardFocusable();
182
183     if (isLink())
184         return document().frameHost()->chrome().client().tabsToLinks();
185     return SVGElement::isKeyboardFocusable();
186 }
187
188 bool SVGAElement::canStartSelection() const
189 {
190     if (!isLink())
191         return SVGElement::canStartSelection();
192     return hasEditableStyle();
193 }
194
195 bool SVGAElement::willRespondToMouseClickEvents()
196 {
197     return isLink() || SVGGraphicsElement::willRespondToMouseClickEvents();
198 }
199
200 } // namespace blink