summaryrefslogtreecommitdiffstats
path: root/WebCore/html/HTMLAnchorElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html/HTMLAnchorElement.cpp')
-rw-r--r--WebCore/html/HTMLAnchorElement.cpp142
1 files changed, 138 insertions, 4 deletions
diff --git a/WebCore/html/HTMLAnchorElement.cpp b/WebCore/html/HTMLAnchorElement.cpp
index f735104..1d5d569 100644
--- a/WebCore/html/HTMLAnchorElement.cpp
+++ b/WebCore/html/HTMLAnchorElement.cpp
@@ -58,6 +58,15 @@ PassRefPtr<HTMLAnchorElement> HTMLAnchorElement::create(const QualifiedName& tag
return adoptRef(new HTMLAnchorElement(tagName, document));
}
+// This function does not allow leading spaces before the port number.
+static unsigned parsePortFromStringPosition(const String& value, unsigned portStart, unsigned& portEnd)
+{
+ portEnd = portStart;
+ while (isASCIIDigit(value[portEnd]))
+ ++portEnd;
+ return value.substring(portStart, portEnd - portStart).toUInt();
+}
+
bool HTMLAnchorElement::supportsFocus() const
{
if (isContentEditable())
@@ -69,10 +78,12 @@ bool HTMLAnchorElement::supportsFocus() const
bool HTMLAnchorElement::isMouseFocusable() const
{
// Anchor elements should be mouse focusable, https://bugs.webkit.org/show_bug.cgi?id=26856
-#if PLATFORM(MAC)
+#if !PLATFORM(GTK) && !PLATFORM(QT)
if (isLink())
- return false;
+ // Only allow links with tabIndex or contentEditable to be mouse focusable.
+ return HTMLElement::supportsFocus();
#endif
+
// Allow tab index etc to control focus.
return HTMLElement::isMouseFocusable();
}
@@ -332,7 +343,7 @@ bool HTMLAnchorElement::hasRel(uint32_t relation) const
void HTMLAnchorElement::setRel(const String& value)
{
m_linkRelations = 0;
- ClassNames newLinkRelations(value, true);
+ SpaceSplitString newLinkRelations(value, true);
// FIXME: Add link relations as they are implemented
if (newLinkRelations.contains("noreferrer"))
m_linkRelations |= RelationNoReferrer;
@@ -360,42 +371,165 @@ String HTMLAnchorElement::hash() const
return fragmentIdentifier.isEmpty() ? "" : "#" + fragmentIdentifier;
}
+void HTMLAnchorElement::setHash(const String& value)
+{
+ KURL url = href();
+ if (value[0] == '#')
+ url.setFragmentIdentifier(value.substring(1));
+ else
+ url.setFragmentIdentifier(value);
+ setHref(url.string());
+}
+
String HTMLAnchorElement::host() const
{
const KURL& url = href();
if (url.hostEnd() == url.pathStart())
return url.host();
- if (SecurityOrigin::isDefaultPortForProtocol(url.port(), url.protocol()))
+ if (isDefaultPortForProtocol(url.port(), url.protocol()))
return url.host();
return url.host() + ":" + String::number(url.port());
}
+void HTMLAnchorElement::setHost(const String& value)
+{
+ if (value.isEmpty())
+ return;
+ KURL url = href();
+ if (!url.canSetHostOrPort())
+ return;
+
+ int separator = value.find(':');
+ if (!separator)
+ return;
+
+ if (separator == -1)
+ url.setHostAndPort(value);
+ else {
+ unsigned portEnd;
+ unsigned port = parsePortFromStringPosition(value, separator + 1, portEnd);
+ if (!port) {
+ // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
+ // specifically goes against RFC 3986 (p3.2) and
+ // requires setting the port to "0" if it is set to empty string.
+ url.setHostAndPort(value.substring(0, separator + 1) + "0");
+ } else {
+ if (isDefaultPortForProtocol(port, url.protocol()))
+ url.setHostAndPort(value.substring(0, separator));
+ else
+ url.setHostAndPort(value.substring(0, portEnd));
+ }
+ }
+ setHref(url.string());
+}
+
String HTMLAnchorElement::hostname() const
{
return href().host();
}
+void HTMLAnchorElement::setHostname(const String& value)
+{
+ // Before setting new value:
+ // Remove all leading U+002F SOLIDUS ("/") characters.
+ unsigned i = 0;
+ unsigned hostLength = value.length();
+ while (value[i] == '/')
+ i++;
+
+ if (i == hostLength)
+ return;
+
+ KURL url = href();
+ if (!url.canSetHostOrPort())
+ return;
+
+ url.setHost(value.substring(i));
+ setHref(url.string());
+}
+
String HTMLAnchorElement::pathname() const
{
return href().path();
}
+void HTMLAnchorElement::setPathname(const String& value)
+{
+ KURL url = href();
+ if (!url.canSetPathname())
+ return;
+
+ if (value[0] == '/')
+ url.setPath(value);
+ else
+ url.setPath("/" + value);
+
+ setHref(url.string());
+}
+
String HTMLAnchorElement::port() const
{
return String::number(href().port());
}
+void HTMLAnchorElement::setPort(const String& value)
+{
+ KURL url = href();
+ if (!url.canSetHostOrPort())
+ return;
+
+ // http://dev.w3.org/html5/spec/infrastructure.html#url-decomposition-idl-attributes
+ // specifically goes against RFC 3986 (p3.2) and
+ // requires setting the port to "0" if it is set to empty string.
+ unsigned port = value.toUInt();
+ if (isDefaultPortForProtocol(port, url.protocol()))
+ url.removePort();
+ else
+ url.setPort(port);
+
+ setHref(url.string());
+}
+
String HTMLAnchorElement::protocol() const
{
return href().protocol() + ":";
}
+void HTMLAnchorElement::setProtocol(const String& value)
+{
+ int separator = value.find(':');
+
+ if (!separator)
+ return;
+ if (value.isEmpty())
+ return;
+
+ KURL url = href();
+ // Following Firefox 3.5.2 which removes anything after the first ":"
+ String newProtocol = value.substring(0, separator);
+ if (!isValidProtocol(newProtocol))
+ return;
+ url.setProtocol(newProtocol);
+
+ setHref(url.string());
+}
+
String HTMLAnchorElement::search() const
{
String query = href().query();
return query.isEmpty() ? "" : "?" + query;
}
+void HTMLAnchorElement::setSearch(const String& value)
+{
+ KURL url = href();
+ String newSearch = (value[0] == '?') ? value.substring(1) : value;
+ // Make sure that '#' in the query does not leak to the hash.
+ url.setQuery(newSearch.replace('#', "%23"));
+
+ setHref(url.string());
+}
+
String HTMLAnchorElement::text() const
{
return innerText();