<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[163253] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/163253">163253</a></dd>
<dt>Author</dt> <dd>mjs@apple.com</dd>
<dt>Date</dt> <dd>2014-02-01 18:18:09 -0800 (Sat, 01 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Factor URL decomposition methods (from URLUtils interface) into a base template
https://bugs.webkit.org/show_bug.cgi?id=128052

Reviewed by Sam Weinig.

Refactoring only; no new tests.

* html/DOMURL.cpp:
* html/DOMURL.h:
(WebCore::DOMURL::href): Moved to header and made inline.
* html/URLUtils.h: Added. 
(WebCore::URLUtils::href): Downcast and call the derived class.
(WebCore::URLUtils::setHref): Downcast and call the derived class.
Functions below factored out from DOMURL.cpp.
(WebCore::URLUtils&lt;T&gt;::toString):
(WebCore::URLUtils&lt;T&gt;::origin):
(WebCore::URLUtils&lt;T&gt;::protocol):
(WebCore::URLUtils&lt;T&gt;::setProtocol):
(WebCore::URLUtils&lt;T&gt;::username):
(WebCore::URLUtils&lt;T&gt;::setUsername):
(WebCore::URLUtils&lt;T&gt;::password):
(WebCore::URLUtils&lt;T&gt;::setPassword):
(WebCore::URLUtils&lt;T&gt;::host):
(WebCore::parsePortFromStringPosition):
(WebCore::URLUtils&lt;T&gt;::setHost):
(WebCore::URLUtils&lt;T&gt;::hostname):
(WebCore::URLUtils&lt;T&gt;::setHostname):
(WebCore::URLUtils&lt;T&gt;::port):
(WebCore::URLUtils&lt;T&gt;::setPort):
(WebCore::URLUtils&lt;T&gt;::pathname):
(WebCore::URLUtils&lt;T&gt;::setPathname):
(WebCore::URLUtils&lt;T&gt;::search):
(WebCore::URLUtils&lt;T&gt;::setSearch):
(WebCore::URLUtils&lt;T&gt;::hash):
(WebCore::URLUtils&lt;T&gt;::setHash):

Add mention of new header.
* GNUmakefile.list.am: 
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.xcodeproj/project.pbxproj:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreGNUmakefilelistam">trunk/Source/WebCore/GNUmakefile.list.am</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxproj">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxprojfilters">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorehtmlDOMURLcpp">trunk/Source/WebCore/html/DOMURL.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlDOMURLh">trunk/Source/WebCore/html/DOMURL.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorehtmlURLUtilsh">trunk/Source/WebCore/html/URLUtils.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/ChangeLog        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2014-02-01  Maciej Stachowiak  &lt;mjs@apple.com&gt;
+
+        Factor URL decomposition methods (from URLUtils interface) into a base template
+        https://bugs.webkit.org/show_bug.cgi?id=128052
+
+        Reviewed by Sam Weinig.
+
+        Refactoring only; no new tests.
+
+        * html/DOMURL.cpp:
+        * html/DOMURL.h:
+        (WebCore::DOMURL::href): Moved to header and made inline.
+        * html/URLUtils.h: Added. 
+        (WebCore::URLUtils::href): Downcast and call the derived class.
+        (WebCore::URLUtils::setHref): Downcast and call the derived class.
+        Functions below factored out from DOMURL.cpp.
+        (WebCore::URLUtils&lt;T&gt;::toString):
+        (WebCore::URLUtils&lt;T&gt;::origin):
+        (WebCore::URLUtils&lt;T&gt;::protocol):
+        (WebCore::URLUtils&lt;T&gt;::setProtocol):
+        (WebCore::URLUtils&lt;T&gt;::username):
+        (WebCore::URLUtils&lt;T&gt;::setUsername):
+        (WebCore::URLUtils&lt;T&gt;::password):
+        (WebCore::URLUtils&lt;T&gt;::setPassword):
+        (WebCore::URLUtils&lt;T&gt;::host):
+        (WebCore::parsePortFromStringPosition):
+        (WebCore::URLUtils&lt;T&gt;::setHost):
+        (WebCore::URLUtils&lt;T&gt;::hostname):
+        (WebCore::URLUtils&lt;T&gt;::setHostname):
+        (WebCore::URLUtils&lt;T&gt;::port):
+        (WebCore::URLUtils&lt;T&gt;::setPort):
+        (WebCore::URLUtils&lt;T&gt;::pathname):
+        (WebCore::URLUtils&lt;T&gt;::setPathname):
+        (WebCore::URLUtils&lt;T&gt;::search):
+        (WebCore::URLUtils&lt;T&gt;::setSearch):
+        (WebCore::URLUtils&lt;T&gt;::hash):
+        (WebCore::URLUtils&lt;T&gt;::setHash):
+
+        Add mention of new header.
+        * GNUmakefile.list.am: 
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.vcxproj/WebCore.vcxproj.filters:
+        * WebCore.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2014-02-01  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Improve the JavaScript bindings of DatasetDOMStringMap
</span></span></pre></div>
<a id="trunkSourceWebCoreGNUmakefilelistam"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/GNUmakefile.list.am (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/GNUmakefile.list.am        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/GNUmakefile.list.am        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -3716,6 +3716,7 @@
</span><span class="cx">         Source/WebCore/html/URLInputType.cpp \
</span><span class="cx">         Source/WebCore/html/URLInputType.h \
</span><span class="cx">         Source/WebCore/html/URLRegistry.h \
</span><ins>+        Source/WebCore/html/URLUtils.h \
</ins><span class="cx">         Source/WebCore/html/ValidationMessage.cpp \
</span><span class="cx">         Source/WebCore/html/ValidationMessage.h \
</span><span class="cx">         Source/WebCore/html/ValidityState.h \
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -20444,6 +20444,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\html\TimeRanges.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\html\TypeAhead.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\html\URLInputType.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\html\URLUtils.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\html\ValidationMessage.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\html\ValidityState.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\html\VoidCallback.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -11081,6 +11081,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\html\URLInputType.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;html&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\html\URLUtils.h&quot;&gt;
+      &lt;Filter&gt;html&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\html\ValidationMessage.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;html&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -8994,6 +8994,7 @@
</span><span class="cx">                 656581E909D1508D000E61D7 /* SVGNames.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGNames.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 656581EA09D1508D000E61D7 /* XLinkNames.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = XLinkNames.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 656581EB09D1508D000E61D7 /* XLinkNames.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = XLinkNames.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                656B9DCA189DE10000BB842C /* URLUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = URLUtils.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 656D371A0ADBA5DE00A4554D /* LoaderNSURLExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LoaderNSURLExtras.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 656D371B0ADBA5DE00A4554D /* LoaderNSURLExtras.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = LoaderNSURLExtras.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 656D371E0ADBA5DE00A4554D /* DocumentLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DocumentLoader.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -17455,6 +17456,7 @@
</span><span class="cx">                                 F55B3DA91251F12D003EF269 /* URLInputType.cpp */,
</span><span class="cx">                                 F55B3DAA1251F12D003EF269 /* URLInputType.h */,
</span><span class="cx">                                 CDEE393817974274001D7580 /* URLRegistry.h */,
</span><ins>+                                656B9DCA189DE10000BB842C /* URLUtils.h */,
</ins><span class="cx">                                 F5A154251279534D00D0B0C0 /* ValidationMessage.cpp */,
</span><span class="cx">                                 F5A154261279534D00D0B0C0 /* ValidationMessage.h */,
</span><span class="cx">                                 15C7708A100D3C6A005BA267 /* ValidityState.h */,
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlDOMURLcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/DOMURL.cpp (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/DOMURL.cpp        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/html/DOMURL.cpp        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -81,11 +81,6 @@
</span><span class="cx">         ec = TypeError;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const URL&amp; DOMURL::href() const
-{
-    return m_url;
-}
-
</del><span class="cx"> void DOMURL::setHref(const String&amp; url)
</span><span class="cx"> {
</span><span class="cx">     m_url = URL(m_baseURL, url);
</span><span class="lines">@@ -98,209 +93,7 @@
</span><span class="cx">         ec = TypeError;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const String&amp; DOMURL::toString() const
-{
-    return href().string();
-}
</del><span class="cx"> 
</span><del>-String DOMURL::origin() const
-{
-    RefPtr&lt;SecurityOrigin&gt; origin = SecurityOrigin::create(href());
-    return origin-&gt;toString();
-}
-
-String DOMURL::protocol() const
-{
-    return href().protocol() + ':';
-}
-
-void DOMURL::setProtocol(const String&amp; value)
-{
-    URL url = href();
-    url.setProtocol(value);
-    setHref(url.string());
-}
-
-String DOMURL::username() const
-{
-    return href().user();
-}
-
-void DOMURL::setUsername(const String&amp; user)
-{
-    URL url = href();
-    url.setUser(user);
-    setHref(url);
-}
-
-String DOMURL::password() const
-{
-    return href().pass();
-}
-
-void DOMURL::setPassword(const String&amp; pass)
-{
-    URL url = href();
-    url.setPass(pass);
-    setHref(url);
-}
-
-String DOMURL::host() const
-{
-    const URL&amp; url = href();
-    if (url.hostEnd() == url.pathStart())
-        return url.host();
-    if (isDefaultPortForProtocol(url.port(), url.protocol()))
-        return url.host();
-    return url.host() + ':' + String::number(url.port());
-}
-
-// This function does not allow leading spaces before the port number.
-static unsigned parsePortFromStringPosition(const String&amp; value, unsigned portStart, unsigned&amp; portEnd)
-{
-    portEnd = portStart;
-    while (isASCIIDigit(value[portEnd]))
-        ++portEnd;
-    return value.substring(portStart, portEnd - portStart).toUInt();
-}
-
-void DOMURL::setHost(const String&amp; value)
-{
-    if (value.isEmpty())
-        return;
-    URL url = href();
-    if (!url.canSetHostOrPort())
-        return;
-
-    size_t separator = value.find(':');
-    if (!separator)
-        return;
-
-    if (separator == notFound)
-        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 &quot;0&quot; 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 DOMURL::hostname() const
-{
-    return href().host();
-}
-
-void DOMURL::setHostname(const String&amp; value)
-{
-    // Before setting new value:
-    // Remove all leading U+002F SOLIDUS (&quot;/&quot;) characters.
-    unsigned i = 0;
-    unsigned hostLength = value.length();
-    while (value[i] == '/')
-        i++;
-
-    if (i == hostLength)
-        return;
-
-    URL url = href();
-    if (!url.canSetHostOrPort())
-        return;
-
-    url.setHost(value.substring(i));
-    setHref(url.string());
-}
-
-String DOMURL::port() const
-{
-    if (href().hasPort())
-        return String::number(href().port());
-
-    return emptyString();
-}
-
-void DOMURL::setPort(const String&amp; value)
-{
-    URL 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 &quot;0&quot; if it is set to empty string.
-    // FIXME: http://url.spec.whatwg.org/ doesn't appear to require this; test what browsers do
-    unsigned port = value.toUInt();
-    if (isDefaultPortForProtocol(port, url.protocol()))
-        url.removePort();
-    else
-        url.setPort(port);
-
-    setHref(url.string());
-}
-
-String DOMURL::pathname() const
-{
-    return href().path();
-}
-
-void DOMURL::setPathname(const String&amp; value)
-{
-    URL url = href();
-    if (!url.canSetPathname())
-        return;
-
-    if (value[0] == '/')
-        url.setPath(value);
-    else
-        url.setPath(&quot;/&quot; + value);
-
-    setHref(url.string());
-}
-
-String DOMURL::search() const
-{
-    String query = href().query();
-    return query.isEmpty() ? emptyString() : &quot;?&quot; + query;
-}
-
-void DOMURL::setSearch(const String&amp; value)
-{
-    URL 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.replaceWithLiteral('#', &quot;%23&quot;));
-
-    setHref(url.string());
-}
-
-String DOMURL::hash() const
-{
-    String fragmentIdentifier = href().fragmentIdentifier();
-    if (fragmentIdentifier.isEmpty())
-        return emptyString();
-    return AtomicString(String(&quot;#&quot; + fragmentIdentifier));
-}
-
-void DOMURL::setHash(const String&amp; value)
-{
-    URL url = href();
-    if (value[0] == '#')
-        url.setFragmentIdentifier(value.substring(1));
-    else
-        url.setFragmentIdentifier(value);
-    setHref(url.string());
-}
-
</del><span class="cx"> #if ENABLE(BLOB)
</span><span class="cx"> 
</span><span class="cx"> String DOMURL::createObjectURL(ScriptExecutionContext* scriptExecutionContext, Blob* blob)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlDOMURLh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/DOMURL.h (163252 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/DOMURL.h        2014-02-02 01:58:16 UTC (rev 163252)
+++ trunk/Source/WebCore/html/DOMURL.h        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ExceptionCode.h&quot;
</span><span class="cx"> #include &quot;URL.h&quot;
</span><ins>+#include &quot;URLUtils.h&quot;
</ins><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="lines">@@ -40,48 +41,17 @@
</span><span class="cx"> class ScriptExecutionContext;
</span><span class="cx"> class URLRegistrable;
</span><span class="cx"> 
</span><del>-class DOMURL : public RefCounted&lt;DOMURL&gt; {
</del><ins>+class DOMURL : public RefCounted&lt;DOMURL&gt;, public URLUtils&lt;DOMURL&gt; {
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><span class="cx">     static PassRefPtr&lt;DOMURL&gt; create(const String&amp; url, const String&amp; base, ExceptionCode&amp;);
</span><span class="cx">     static PassRefPtr&lt;DOMURL&gt; create(const String&amp; url, const DOMURL* base, ExceptionCode&amp;);
</span><span class="cx">     static PassRefPtr&lt;DOMURL&gt; create(const String&amp; url, ExceptionCode&amp;);
</span><span class="cx"> 
</span><del>-    const URL&amp; href() const;
</del><ins>+    URL href() const { return m_url; }
</ins><span class="cx">     void setHref(const String&amp; url);
</span><span class="cx">     void setHref(const String&amp;, ExceptionCode&amp;);
</span><del>-    const String&amp; toString() const;
</del><span class="cx"> 
</span><del>-    String origin() const;
-
-    String protocol() const;
-    void setProtocol(const String&amp;);
-
-    String username() const;
-    void setUsername(const String&amp;);
-
-    String password() const;
-    void setPassword(const String&amp;);
-
-    String host() const;
-    void setHost(const String&amp;);
-
-    String hostname() const;
-    void setHostname(const String&amp;);
-
-    String port() const;
-    void setPort(const String&amp;);
-
-    String pathname() const;
-    void setPathname(const String&amp;);
-
-    String search() const;
-    void setSearch(const String&amp;);
-
-    String hash() const;
-    void setHash(const String&amp;);
-
-
</del><span class="cx"> #if ENABLE(BLOB)
</span><span class="cx">     static void contextDestroyed(ScriptExecutionContext*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlURLUtilsh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/html/URLUtils.h (0 => 163253)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/URLUtils.h                                (rev 0)
+++ trunk/Source/WebCore/html/URLUtils.h        2014-02-02 02:18:09 UTC (rev 163253)
</span><span class="lines">@@ -0,0 +1,296 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef URLUtils_h
+#define URLUtils_h
+
+#include &quot;SecurityOrigin.h&quot;
+
+namespace WebCore {
+
+template &lt;typename T&gt;
+class URLUtils {
+public:
+    URL href() const { return static_cast&lt;const T*&gt;(this)-&gt;href(); }
+    void setHref(const String&amp; url) { static_cast&lt;T*&gt;(this)-&gt;setHref(url); }
+
+    String toString() const;
+
+    String origin() const;
+
+    String protocol() const;
+    void setProtocol(const String&amp;);
+
+    String username() const;
+    void setUsername(const String&amp;);
+
+    String password() const;
+    void setPassword(const String&amp;);
+
+    String host() const;
+    void setHost(const String&amp;);
+
+    String hostname() const;
+    void setHostname(const String&amp;);
+
+    String port() const;
+    void setPort(const String&amp;);
+
+    String pathname() const;
+    void setPathname(const String&amp;);
+
+    String search() const;
+    void setSearch(const String&amp;);
+
+    String hash() const;
+    void setHash(const String&amp;);
+};
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::toString() const
+{
+    return href().string();
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::origin() const
+{
+    RefPtr&lt;SecurityOrigin&gt; origin = SecurityOrigin::create(href());
+    return origin-&gt;toString();
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::protocol() const
+{
+    return href().protocol() + ':';
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setProtocol(const String&amp; value)
+{
+    URL url = href();
+    url.setProtocol(value);
+    setHref(url.string());
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::username() const
+{
+    return href().user();
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setUsername(const String&amp; user)
+{
+    URL url = href();
+    url.setUser(user);
+    setHref(url);
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::password() const
+{
+    return href().pass();
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setPassword(const String&amp; pass)
+{
+    URL url = href();
+    url.setPass(pass);
+    setHref(url);
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::host() const
+{
+    const URL&amp; url = href();
+    if (url.hostEnd() == url.pathStart())
+        return url.host();
+    if (isDefaultPortForProtocol(url.port(), url.protocol()))
+        return url.host();
+    return url.host() + ':' + String::number(url.port());
+}
+
+// This function does not allow leading spaces before the port number.
+static inline unsigned parsePortFromStringPosition(const String&amp; value, unsigned portStart, unsigned&amp; portEnd)
+{
+    portEnd = portStart;
+    while (isASCIIDigit(value[portEnd]))
+        ++portEnd;
+    return value.substring(portStart, portEnd - portStart).toUInt();
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setHost(const String&amp; value)
+{
+    if (value.isEmpty())
+        return;
+    URL url = href();
+    if (!url.canSetHostOrPort())
+        return;
+
+    size_t separator = value.find(':');
+    if (!separator)
+        return;
+
+    if (separator == notFound)
+        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 &quot;0&quot; 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());
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::hostname() const
+{
+    return href().host();
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setHostname(const String&amp; value)
+{
+    // Before setting new value:
+    // Remove all leading U+002F SOLIDUS (&quot;/&quot;) characters.
+    unsigned i = 0;
+    unsigned hostLength = value.length();
+    while (value[i] == '/')
+        i++;
+
+    if (i == hostLength)
+        return;
+
+    URL url = href();
+    if (!url.canSetHostOrPort())
+        return;
+
+    url.setHost(value.substring(i));
+    setHref(url.string());
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::port() const
+{
+    if (href().hasPort())
+        return String::number(href().port());
+
+    return emptyString();
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setPort(const String&amp; value)
+{
+    URL 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 &quot;0&quot; if it is set to empty string.
+    // FIXME: http://url.spec.whatwg.org/ doesn't appear to require this; test what browsers do
+    unsigned port = value.toUInt();
+    if (isDefaultPortForProtocol(port, url.protocol()))
+        url.removePort();
+    else
+        url.setPort(port);
+
+    setHref(url.string());
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::pathname() const
+{
+    return href().path();
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setPathname(const String&amp; value)
+{
+    URL url = href();
+    if (!url.canSetPathname())
+        return;
+
+    if (value[0] == '/')
+        url.setPath(value);
+    else
+        url.setPath(&quot;/&quot; + value);
+
+    setHref(url.string());
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::search() const
+{
+    String query = href().query();
+    return query.isEmpty() ? emptyString() : &quot;?&quot; + query;
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setSearch(const String&amp; value)
+{
+    URL 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.replaceWithLiteral('#', &quot;%23&quot;));
+
+    setHref(url.string());
+}
+
+template &lt;typename T&gt;
+String URLUtils&lt;T&gt;::hash() const
+{
+    String fragmentIdentifier = href().fragmentIdentifier();
+    if (fragmentIdentifier.isEmpty())
+        return emptyString();
+    return AtomicString(String(&quot;#&quot; + fragmentIdentifier));
+}
+
+template &lt;typename T&gt;
+void URLUtils&lt;T&gt;::setHash(const String&amp; value)
+{
+    URL url = href();
+    if (value[0] == '#')
+        url.setFragmentIdentifier(value.substring(1));
+    else
+        url.setFragmentIdentifier(value);
+    setHref(url.string());
+}
+
+} // namespace WebCore
+
+#endif // URLUtils_h
</ins></span></pre>
</div>
</div>

</body>
</html>