diff options
Diffstat (limited to 'WebCore/html/HTMLAnchorElement.cpp')
-rw-r--r-- | WebCore/html/HTMLAnchorElement.cpp | 142 |
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(); |