<!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>[214252] trunk</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/214252">214252</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-22 10:14:36 -0700 (Wed, 22 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>XMLHttpRequest: getAllResponseHeaders() should lowercase header names before sorting
https://bugs.webkit.org/show_bug.cgi?id=169286

Patch by Youenn Fablet &lt;youenn@apple.com&gt; on 2017-03-22
Reviewed by Chris Dumez.

LayoutTests/imported/w3c:

* web-platform-tests/XMLHttpRequest/getallresponseheaders-cl-expected.txt:
* web-platform-tests/XMLHttpRequest/getallresponseheaders-expected.txt:

Source/WebCore:

Covered by rebased tests.

https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method now mandates to lowercase the header names and
sort them before appending them. This ensures that differences in the way headers are processed by browsers are
not visible to web pages. This also moves towards lowercased/case-insensitive header processing which should be
the norm.

* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::getAllResponseHeaders): Lower-casing, then sorting, then serializing headers.
* xml/XMLHttpRequest.h: Storing getAllResponseHeaders result if case needed again.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsXMLHttpRequestgetallresponseheadersclexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-cl-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsXMLHttpRequestgetallresponseheadersexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestcpp">trunk/Source/WebCore/xml/XMLHttpRequest.cpp</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequesth">trunk/Source/WebCore/xml/XMLHttpRequest.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (214251 => 214252)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog        2017-03-22 16:15:16 UTC (rev 214251)
+++ trunk/LayoutTests/imported/w3c/ChangeLog        2017-03-22 17:14:36 UTC (rev 214252)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2017-03-22  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        XMLHttpRequest: getAllResponseHeaders() should lowercase header names before sorting
+        https://bugs.webkit.org/show_bug.cgi?id=169286
+
+        Reviewed by Chris Dumez.
+
+        * web-platform-tests/XMLHttpRequest/getallresponseheaders-cl-expected.txt:
+        * web-platform-tests/XMLHttpRequest/getallresponseheaders-expected.txt:
+
</ins><span class="cx"> 2017-03-22  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement the &quot;noopener&quot; feature for window.open()
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsXMLHttpRequestgetallresponseheadersclexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-cl-expected.txt (214251 => 214252)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-cl-expected.txt        2017-03-22 16:15:16 UTC (rev 214251)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-cl-expected.txt        2017-03-22 17:14:36 UTC (rev 214252)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> 
</span><del>-FAIL Casing of known headers assert_equals: expected &quot;content-length: 0\r\n&quot; but got &quot;Content-Length: 0\r\n&quot;
</del><ins>+PASS Casing of known headers 
</ins><span class="cx"> FAIL Casing of known headers 1 assert_regexp_match: expected object &quot;/content-TYPE/&quot; but got &quot;&quot;
</span><span class="cx"> FAIL Casing of known headers 2 assert_regexp_match: expected object &quot;/THIS-is-A-test: 1, 2/&quot; but got &quot;&quot;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsXMLHttpRequestgetallresponseheadersexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-expected.txt (214251 => 214252)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-expected.txt        2017-03-22 16:15:16 UTC (rev 214251)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/getallresponseheaders-expected.txt        2017-03-22 17:14:36 UTC (rev 214252)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><span class="cx"> 
</span><span class="cx"> PASS XMLHttpRequest: getAllResponseHeaders() 
</span><del>-FAIL XMLHttpRequest: getAllResponseHeaders() 1 assert_equals: expected &quot;also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n&quot; but got &quot;ALSO-here: Mr. PB\r\nFOO-test: 1, 2\r\newok: lego\r\n&quot;
</del><ins>+PASS XMLHttpRequest: getAllResponseHeaders() 1 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214251 => 214252)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-22 16:15:16 UTC (rev 214251)
+++ trunk/Source/WebCore/ChangeLog        2017-03-22 17:14:36 UTC (rev 214252)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2017-03-22  Youenn Fablet  &lt;youenn@apple.com&gt;
+
+        XMLHttpRequest: getAllResponseHeaders() should lowercase header names before sorting
+        https://bugs.webkit.org/show_bug.cgi?id=169286
+
+        Reviewed by Chris Dumez.
+
+        Covered by rebased tests.
+
+        https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method now mandates to lowercase the header names and
+        sort them before appending them. This ensures that differences in the way headers are processed by browsers are
+        not visible to web pages. This also moves towards lowercased/case-insensitive header processing which should be
+        the norm.
+
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::getAllResponseHeaders): Lower-casing, then sorting, then serializing headers.
+        * xml/XMLHttpRequest.h: Storing getAllResponseHeaders result if case needed again.
+
</ins><span class="cx"> 2017-03-22  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement the &quot;noopener&quot; feature for window.open()
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (214251 => 214252)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2017-03-22 16:15:16 UTC (rev 214251)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2017-03-22 17:14:36 UTC (rev 214252)
</span><span class="lines">@@ -930,18 +930,27 @@
</span><span class="cx">     if (m_state &lt; HEADERS_RECEIVED || m_error)
</span><span class="cx">         return emptyString();
</span><span class="cx"> 
</span><del>-    StringBuilder stringBuilder;
</del><ins>+    if (!m_allResponseHeaders) {
+        Vector&lt;String&gt; headers;
+        headers.reserveInitialCapacity(m_response.httpHeaderFields().size());
</ins><span class="cx"> 
</span><del>-    for (const auto&amp; header : m_response.httpHeaderFields()) {
-        stringBuilder.append(header.key);
-        stringBuilder.append(':');
-        stringBuilder.append(' ');
-        stringBuilder.append(header.value);
-        stringBuilder.append('\r');
-        stringBuilder.append('\n');
</del><ins>+        for (auto&amp; header : m_response.httpHeaderFields()) {
+            StringBuilder stringBuilder;
+            stringBuilder.append(header.key.convertToASCIILowercase());
+            stringBuilder.append(&quot;: &quot;);
+            stringBuilder.append(header.value);
+            stringBuilder.append(&quot;\r\n&quot;);
+            headers.uncheckedAppend(stringBuilder.toString());
+        }
+        std::sort(headers.begin(), headers.end(), WTF::codePointCompareLessThan);
+
+        StringBuilder stringBuilder;
+        for (auto&amp; header : headers)
+            stringBuilder.append(header);
+        m_allResponseHeaders = stringBuilder.toString();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return stringBuilder.toString();
</del><ins>+    return m_allResponseHeaders;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String XMLHttpRequest::getResponseHeader(const String&amp; name) const
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (214251 => 214252)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.h        2017-03-22 16:15:16 UTC (rev 214251)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h        2017-03-22 17:14:36 UTC (rev 214252)
</span><span class="lines">@@ -229,6 +229,7 @@
</span><span class="cx"> 
</span><span class="cx">     ResponseType m_responseType { ResponseType::EmptyString };
</span><span class="cx">     bool m_responseCacheIsValid { false };
</span><ins>+    mutable String m_allResponseHeaders;
</ins><span class="cx"> 
</span><span class="cx">     Timer m_resumeTimer;
</span><span class="cx">     bool m_dispatchErrorOnResuming { false };
</span></span></pre>
</div>
</div>

</body>
</html>