<!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>[161532] 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/161532">161532</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-01-08 18:11:59 -0800 (Wed, 08 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Source/WebCore: Correctly set XHR loadend attributes (loaded and total).
https://bugs.webkit.org/show_bug.cgi?id=120828

Patch by Youenn Fablet &lt;youennf@gmail.com&gt; on 2014-01-08
Reviewed by Alexey Proskuryakov.

Added correct initialization of lengthComputable, loaded and total attributes
to XHR ProgressEvent events (load, loadstart, loadend, abort, error and timeout).

XMLHttpRequestProgressEventThrottle and XMLHttpRequestUpload now keep persistent knowledge
of m_loaded and m_total values with this patch.

Code refactoring to handle event dispatching in case of error in a single manner.
XMLHttpRequestProgressEventThrottle::dispatchProgressEvent is renamed as dispatchThrottledProgressEvent
XMLHttpRequestProgressEventThrottle::dispatchEventAndLoadend is replaced by dispatchProgressEvent(const AtomicString&amp;)

Tests: http/tests/xmlhttprequest/loadstart-event-init.html
       http/tests/xmlhttprequest/onabort-progressevent-attributes.html
       http/tests/xmlhttprequest/onload-progressevent-attributes.html
       http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html
       http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html

* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::callReadyStateChangeListener): changed readystatechange event from ProgressEvent to Event (not cancellable, not bubblable) to better match the spec
(WebCore::XMLHttpRequest::createRequest):
(WebCore::XMLHttpRequest::abort): code refactoring to handle error event dispatching in a single way
(WebCore::XMLHttpRequest::networkError): code refactoring to handle error event dispatching in a single way
(WebCore::XMLHttpRequest::abortError): code refactoring to handle error event dispatching in a single way
(WebCore::XMLHttpRequest::didSendData):
(WebCore::XMLHttpRequest::didReceiveData):
(WebCore::XMLHttpRequest::dispatchErrorEvents): dispatch progress events in case of error
(WebCore::XMLHttpRequest::didTimeout): code refactoring to handle error event dispatching in a single way
* xml/XMLHttpRequest.h:
* xml/XMLHttpRequestProgressEventThrottle.cpp: before the patch, the fact that a progress event is being throttled is stored indirectly (m_loaded or m_total not equal to zero). With the patch, this information is stored in m_hasThrottledProgressEvent. The m_loaded and m_total values are no longer set back to zero after a progress event is dispatched. This allows using these values to correctly initialize other ProgressEvent events (in particular loadend, abort, timeout...)
(WebCore::XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle):
(WebCore::XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent): always update the new m_loaded and m_total values. If progress event is not sent as part of the function call, store the fact that a progress event is being throttled through m_hasThrottledProgressEvent.
(WebCore::XMLHttpRequestProgressEventThrottle::dispatchProgressEvent): used to send any ProgressEvent event that is not be throttled
(WebCore::XMLHttpRequestProgressEventThrottle::flushProgressEvent): after the call, no progress event is throttled anymore
(WebCore::XMLHttpRequestProgressEventThrottle::fired): after the call, no progress event is throttled anymore
(WebCore::XMLHttpRequestProgressEventThrottle::hasEventToDispatch):
(WebCore::XMLHttpRequestProgressEventThrottle::suspend):
* xml/XMLHttpRequestProgressEventThrottle.h: introduced m_hasThrottledProgressEvent which stores whether a progress event is being throttled and m_computableLength which is used to initialize ProgressEvent computableLength
* xml/XMLHttpRequestUpload.cpp:
(WebCore::XMLHttpRequestUpload::XMLHttpRequestUpload):
(WebCore::XMLHttpRequestUpload::dispatchProgressEvent):
* xml/XMLHttpRequestUpload.h: introduced m_loaded, m_total and m_lengthComputable, similarly to XMLHttpRequestProgressEventThrottle

LayoutTests: Correctly set XHR loadend event attributes (loaded and total).
https://bugs.webkit.org/show_bug.cgi?id=120828

Patch by Youenn Fablet &lt;youennf@gmail.com&gt; on 2014-01-08
Reviewed by Alexey Proskuryakov.

Tests for abort, load, loadstart and loadend ProgressEvent events for XMLHttpRequest and XMLHttpRequestUpload

* fast/xmlhttprequest/xmlhttprequest-get-expected.txt: Changed to correct event values
* http/tests/xmlhttprequest/loadstart-event-init-expected.txt: Added.
* http/tests/xmlhttprequest/loadstart-event-init.html: Added.
* http/tests/xmlhttprequest/onabort-progressevent-attributes-expected.txt: Added.
* http/tests/xmlhttprequest/onabort-progressevent-attributes.html: Added.
* http/tests/xmlhttprequest/onload-progressevent-attributes-expected.txt: Added.
* http/tests/xmlhttprequest/onload-progressevent-attributes.html: Added.
* http/tests/xmlhttprequest/upload-onabort-progressevent-attributes-expected.txt: Added.
* http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html: Added.
* http/tests/xmlhttprequest/upload-onload-progressevent-attributes-expected.txt: Added.
* http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastxmlhttprequestxmlhttprequestgetexpectedtxt">trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-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>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestProgressEventThrottlecpp">trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestProgressEventThrottleh">trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestUploadcpp">trunk/Source/WebCore/xml/XMLHttpRequestUpload.cpp</a></li>
<li><a href="#trunkSourceWebCorexmlXMLHttpRequestUploadh">trunk/Source/WebCore/xml/XMLHttpRequestUpload.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestloadstarteventinitexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestloadstarteventinithtml">trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init.html</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestonabortprogresseventattributesexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestonabortprogresseventattributeshtml">trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes.html</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestonloadprogresseventattributesexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestonloadprogresseventattributeshtml">trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes.html</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestuploadonabortprogresseventattributesexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestuploadonabortprogresseventattributeshtml">trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestuploadonloadprogresseventattributesexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequestuploadonloadprogresseventattributeshtml">trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/LayoutTests/ChangeLog        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2014-01-08  Youenn Fablet  &lt;youennf@gmail.com&gt;
+
+        Correctly set XHR loadend event attributes (loaded and total).
+        https://bugs.webkit.org/show_bug.cgi?id=120828
+
+        Reviewed by Alexey Proskuryakov.
+
+        Tests for abort, load, loadstart and loadend ProgressEvent events for XMLHttpRequest and XMLHttpRequestUpload
+
+        * fast/xmlhttprequest/xmlhttprequest-get-expected.txt: Changed to correct event values
+        * http/tests/xmlhttprequest/loadstart-event-init-expected.txt: Added.
+        * http/tests/xmlhttprequest/loadstart-event-init.html: Added.
+        * http/tests/xmlhttprequest/onabort-progressevent-attributes-expected.txt: Added.
+        * http/tests/xmlhttprequest/onabort-progressevent-attributes.html: Added.
+        * http/tests/xmlhttprequest/onload-progressevent-attributes-expected.txt: Added.
+        * http/tests/xmlhttprequest/onload-progressevent-attributes.html: Added.
+        * http/tests/xmlhttprequest/upload-onabort-progressevent-attributes-expected.txt: Added.
+        * http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html: Added.
+        * http/tests/xmlhttprequest/upload-onload-progressevent-attributes-expected.txt: Added.
+        * http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html: Added.
+
</ins><span class="cx"> 2014-01-07  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         a fractional value of the css letter-spacing property is not rendered as expected
</span></span></pre></div>
<a id="trunkLayoutTestsfastxmlhttprequestxmlhttprequestgetexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -53,9 +53,9 @@
</span><span class="cx"> initEvent : 'function initEvent() {
</span><span class="cx">     [native code]
</span><span class="cx"> }'
</span><del>-lengthComputable : 'false'
-loaded : '0'
-position : '0'
</del><ins>+lengthComputable : 'true'
+loaded : '174'
+position : '174'
</ins><span class="cx"> preventDefault : 'function preventDefault() {
</span><span class="cx">     [native code]
</span><span class="cx"> }'
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">     [native code]
</span><span class="cx"> }'
</span><span class="cx"> target : '[object XMLHttpRequest]'
</span><del>-total : '0'
-totalSize : '0'
</del><ins>+total : '174'
+totalSize : '174'
</ins><span class="cx"> type : 'load'
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestloadstarteventinitexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init-expected.txt (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init-expected.txt        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS XMLHttpRequest: ensure loadstart event progress members are correctly initialized 
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestloadstarteventinithtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init.html (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/loadstart-event-init.html        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;title&gt;XMLHttpRequest: ensure loadstart event progress members are correctly initialized&lt;/title&gt;
+    &lt;script src=&quot;/js-test-resources/testharness.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;/js-test-resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+
+&lt;body&gt;
+    &lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+
+    &lt;script type=&quot;text/javascript&quot;&gt;
+        var test = async_test()
+        test.step(function() {
+            var count = 0;
+            var xhr = new XMLHttpRequest();
+
+            xhr.onloadstart = test.step_func(function(e)
+            {
+                assert_equals(e.loaded, 0, &quot;loaded member of xhr.loadstart event should be 0&quot;)
+                if (count == 1) {
+                    test.done();
+                }
+            })
+
+            xhr.upload.onloadstart = test.step_func(function(e)
+            {
+                assert_equals(e.loaded, 0, &quot;loaded member of xhr.upload.loadstart event should be 0&quot;);
+            })
+
+            xhr.onloadend = function(e)
+            {
+                if (count++ &lt; 1) {
+                    xhr.open(&quot;POST&quot;, &quot;./resources/content.php&quot;, true);
+                    xhr.send(&quot;test&quot;);
+                }                    
+            }
+
+            xhr.open(&quot;POST&quot;, &quot;./resources/content.php&quot;, true);
+            xhr.send(&quot;test&quot;);
+        });
+    &lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestonabortprogresseventattributesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes-expected.txt (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes-expected.txt        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+Test case for bug 120828: Correctly set XHR loadend attributes (loaded and total).
+
+Verify that abort and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.
+
+PASS
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestonabortprogresseventattributeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes.html (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onabort-progressevent-attributes.html        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Test case for bug 120828 (abort case)&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p&gt;Test case for &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=120828&quot;&gt; bug 120828&lt;/a&gt;: Correctly set XHR loadend attributes (loaded and total).&lt;/p&gt;
+&lt;p&gt;Verify that abort and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.&lt;/p&gt;
+&lt;p id=console&gt;&lt;/p&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+var status = &quot;PASS&quot;;
+var total = 0;
+var loaded = 0;
+
+function onProgressEvent(e)
+{
+    if (total != e.total || loaded != e.loaded)
+        fail(&quot;Event &quot; + e.type + &quot;total/loaded values not matching: &quot; 
+            + &quot;(&quot; + e.loaded + &quot; / &quot; + e.total + &quot;), expected (&quot; + loaded + &quot; / &quot; + total + &quot;)&quot;);
+}
+
+function onUnexpectedProgressEvent(e)
+{
+    fail(&quot;unexpected ProgressEvent: &quot; + e.type);
+}
+
+function fail(msg)
+{
+    status = &quot;FAILED: &quot; + msg;
+    completeTest();
+    status = &quot;&quot;;
+}
+
+function completeTest()
+{
+    log(status);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function test() 
+{
+    var iteration = 2;
+    var delay = &quot;1000&quot;;
+
+    var req = new XMLHttpRequest();
+    req.onprogress = function(e){
+        total = e.total;
+        loaded = e.loaded;
+        req.abort();
+    };
+    req.onerror = onUnexpectedProgressEvent;
+    req.onabort = onProgressEvent;
+    req.onloadend = function(e) {
+        onProgressEvent(e);
+        completeTest();
+    }
+    req.open(&quot;GET&quot;, &quot;resources/download-with-delay.php?iteration=&quot; + iteration + &quot;&amp;delay=&quot; + delay, true);
+    req.send(null);
+
+}
+
+function log(message)
+{
+    var consoleElt = document.getElementById(&quot;console&quot;);
+    consoleElt.innerHTML += message + &quot;&lt;br/&gt;&quot;;
+}
+
+test(); 
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestonloadprogresseventattributesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes-expected.txt (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes-expected.txt        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+Test case for bug 120828: Correctly set XHR loadend attributes (loaded and total).
+
+Verify that load and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.
+
+PASS
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestonloadprogresseventattributeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes.html (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onload-progressevent-attributes.html        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Test case for bug 120828&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p&gt; Test case for &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=120828&quot;&gt; bug 120828&lt;/a&gt;: Correctly set XHR loadend attributes (loaded and total).&lt;/p&gt;
+&lt;p&gt; Verify that load and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.&lt;/p&gt;
+&lt;p id=console&gt;&lt;/p&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+var status = &quot;PASS&quot;;
+var total = 0;
+var loaded = 0;
+
+function onProgressEvent(e)
+{
+    if (total != e.total || loaded != e.loaded)
+        fail(&quot;Event &quot; + e.type + &quot; total/loaded values not matching: &quot; 
+            + &quot;(&quot; + e.loaded + &quot; / &quot; + e.total + &quot;), expected (&quot; + loaded + &quot; / &quot; + total + &quot;)&quot;);
+}
+
+function onUnexpectedProgressEvent(e)
+{
+    fail(&quot;unexpected ProgressEvent: &quot; + e.type);
+}
+
+function fail(msg)
+{
+    status = &quot;FAILED: &quot; + msg;
+    completeTest();
+    status = &quot;&quot;;
+}
+
+function completeTest()
+{
+    log(status);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function test() 
+{
+    var req = new XMLHttpRequest();
+    req.onreadystatechange = function(e) {
+        if (req.readyState == req.DONE) {
+            if (this.status == 200)
+                total = loaded = req.responseText.length;
+            else
+                fail(&quot;unexpected status: &quot; + status);
+        }
+    }
+    req.onabort = onUnexpectedProgressEvent;
+    req.onerror = onUnexpectedProgressEvent;
+    req.onload = onProgressEvent;
+    req.onloadend = function(e) {
+        onProgressEvent(e);
+        completeTest();
+    }
+
+    req.open(&quot;GET&quot;, &quot;resources/get.txt&quot;, true); 
+    req.send();
+}
+
+function log(message)
+{
+    var consoleElt = document.getElementById(&quot;console&quot;);
+    consoleElt.innerHTML += message + &quot;&lt;br/&gt;&quot;;
+}
+
+test(); 
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestuploadonabortprogresseventattributesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes-expected.txt (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes-expected.txt        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+Test case for bug 120828: Correctly set XHR loadend attributes (loaded and total).
+
+Upload case: verify that abort and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.
+
+PASS
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestuploadonabortprogresseventattributeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Test case for bug 120828 (abort case)&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p&gt;Test case for &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=120828&quot;&gt; bug 120828&lt;/a&gt;: Correctly set XHR loadend attributes (loaded and total).&lt;/p&gt;
+&lt;p&gt;Upload case: verify that abort and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.&lt;/p&gt;
+&lt;p id=console&gt;&lt;/p&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+var status = &quot;PASS&quot;;
+var total = 1;
+var loaded = 1;
+var uploadedData = &quot;d&quot;;
+
+function onProgressEvent(e)
+{
+    if (!e.lengthComputable)
+        fail(&quot;Event &quot; + e.type + &quot; lengthComputable is false&quot;);
+    if (e.total != total || e.loaded != loaded)
+        fail(&quot;Event &quot; + e.type + &quot; total/loaded values not matching: &quot; 
+            + &quot;(&quot; + e.loaded + &quot; / &quot; + e.total + &quot;), expected (&quot; + loaded + &quot; / &quot; + total + &quot;)&quot;);
+}
+
+function onUnexpectedProgressEvent(e)
+{
+    fail(&quot;unexpected ProgressEvent: &quot; + e.type);
+}
+
+function fail(msg)
+{
+    status = &quot;FAILED: &quot; + msg;
+    completeTest();
+    status = &quot;&quot;;
+}
+
+function completeTest()
+{
+    log(status);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function test()
+{
+    var req = new XMLHttpRequest();
+    req.upload.onerror = onUnexpectedProgressEvent;
+    req.upload.onload = onUnexpectedProgressEvent;
+    req.upload.onabort = onProgressEvent;
+    req.upload.onprogress = function(e) {
+        onProgressEvent(e);
+        req.abort();
+    }
+    req.upload.onloadend = function(e) {
+        onProgressEvent(e);
+        completeTest();
+    }
+
+    req.open(&quot;POST&quot;, &quot;resources/post-echo.cgi&quot;, true);
+    req.send(uploadedData);
+}
+
+
+function log(message)
+{
+    var consoleElt = document.getElementById(&quot;console&quot;);
+    consoleElt.innerHTML += message + &quot;&lt;br/&gt;&quot;;
+}
+
+test(); 
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestuploadonloadprogresseventattributesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes-expected.txt (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes-expected.txt        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+Test case for bug 120828: Correctly set XHR loadend attributes (loaded and total).
+
+Upload case: verify that load and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.
+
+PASS
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequestuploadonloadprogresseventattributeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html (0 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Test case for bug 120828&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p&gt; Test case for &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=120828&quot;&gt; bug 120828&lt;/a&gt;: Correctly set XHR loadend attributes (loaded and total).&lt;/p&gt;
+&lt;p&gt; Upload case: verify that load and loadend events have their ProgressEvent attributes (loaded, total and lengthComputable) correctly set.&lt;/p&gt;
+&lt;p id=console&gt;&lt;/p&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+var status = &quot;PASS&quot;;
+var total = 1;
+var loaded = 1;
+var uploadedData = &quot;d&quot;;
+
+function onProgressEvent(e)
+{
+    if (!e.lengthComputable)
+        fail(&quot;Event &quot; + e.type + &quot;event lengthComputable = false&quot;);
+    if (e.total != total || e.loaded != loaded)
+        fail(&quot;Event &quot; + e.type + &quot;total/loaded values not matching: &quot;
+            + &quot;(&quot; + e.loaded + &quot; / &quot; + e.total + &quot;), expected (&quot; + loaded + &quot; / &quot; + total + &quot;)&quot;);
+}
+
+function onUnexpectedProgressEvent(e)
+{
+    fail(&quot;unexpected ProgressEvent: &quot; + e.type);
+}
+
+function fail(msg)
+{
+    status = &quot;FAILED: &quot; + msg;
+    completeTest();
+    status = &quot;&quot;;
+}
+
+function completeTest()
+{
+    log(status);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function test()
+{
+    var req = new XMLHttpRequest();
+    req.upload.onabort = onUnexpectedProgressEvent;
+    req.upload.onerror = onUnexpectedProgressEvent;
+    req.upload.onprogress = onProgressEvent;
+    req.upload.onload = onProgressEvent;
+    req.upload.onloadend = function(e) {
+        onProgressEvent(e);
+        completeTest();
+    }
+
+    req.open(&quot;POST&quot;, &quot;resources/post-echo.cgi&quot;, true);
+    req.send(uploadedData);
+}
+
+function log(message)
+{
+    var consoleElt = document.getElementById(&quot;console&quot;);
+    consoleElt.innerHTML += message + &quot;&lt;br/&gt;&quot;;
+}
+
+test(); 
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/ChangeLog        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2014-01-08  Youenn Fablet  &lt;youennf@gmail.com&gt;
+
+        Correctly set XHR loadend attributes (loaded and total).
+        https://bugs.webkit.org/show_bug.cgi?id=120828
+
+        Reviewed by Alexey Proskuryakov.
+        
+        Added correct initialization of lengthComputable, loaded and total attributes 
+        to XHR ProgressEvent events (load, loadstart, loadend, abort, error and timeout).
+
+        XMLHttpRequestProgressEventThrottle and XMLHttpRequestUpload now keep persistent knowledge 
+        of m_loaded and m_total values with this patch.
+        
+        Code refactoring to handle event dispatching in case of error in a single manner.
+        XMLHttpRequestProgressEventThrottle::dispatchProgressEvent is renamed as dispatchThrottledProgressEvent
+        XMLHttpRequestProgressEventThrottle::dispatchEventAndLoadend is replaced by dispatchProgressEvent(const AtomicString&amp;)
+
+        Tests: http/tests/xmlhttprequest/loadstart-event-init.html
+               http/tests/xmlhttprequest/onabort-progressevent-attributes.html
+               http/tests/xmlhttprequest/onload-progressevent-attributes.html
+               http/tests/xmlhttprequest/upload-onabort-progressevent-attributes.html
+               http/tests/xmlhttprequest/upload-onload-progressevent-attributes.html
+
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::callReadyStateChangeListener): changed readystatechange event from ProgressEvent to Event (not cancellable, not bubblable) to better match the spec 
+        (WebCore::XMLHttpRequest::createRequest):
+        (WebCore::XMLHttpRequest::abort): code refactoring to handle error event dispatching in a single way
+        (WebCore::XMLHttpRequest::networkError): code refactoring to handle error event dispatching in a single way
+        (WebCore::XMLHttpRequest::abortError): code refactoring to handle error event dispatching in a single way
+        (WebCore::XMLHttpRequest::didSendData):
+        (WebCore::XMLHttpRequest::didReceiveData):
+        (WebCore::XMLHttpRequest::dispatchErrorEvents): dispatch progress events in case of error
+        (WebCore::XMLHttpRequest::didTimeout): code refactoring to handle error event dispatching in a single way
+        * xml/XMLHttpRequest.h:
+        * xml/XMLHttpRequestProgressEventThrottle.cpp: before the patch, the fact that a progress event is being throttled is stored indirectly (m_loaded or m_total not equal to zero). With the patch, this information is stored in m_hasThrottledProgressEvent. The m_loaded and m_total values are no longer set back to zero after a progress event is dispatched. This allows using these values to correctly initialize other ProgressEvent events (in particular loadend, abort, timeout...) 
+        (WebCore::XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle):
+        (WebCore::XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent): always update the new m_loaded and m_total values. If progress event is not sent as part of the function call, store the fact that a progress event is being throttled through m_hasThrottledProgressEvent. 
+        (WebCore::XMLHttpRequestProgressEventThrottle::dispatchProgressEvent): used to send any ProgressEvent event that is not be throttled
+        (WebCore::XMLHttpRequestProgressEventThrottle::flushProgressEvent): after the call, no progress event is throttled anymore
+        (WebCore::XMLHttpRequestProgressEventThrottle::fired): after the call, no progress event is throttled anymore
+        (WebCore::XMLHttpRequestProgressEventThrottle::hasEventToDispatch):
+        (WebCore::XMLHttpRequestProgressEventThrottle::suspend):
+        * xml/XMLHttpRequestProgressEventThrottle.h: introduced m_hasThrottledProgressEvent which stores whether a progress event is being throttled and m_computableLength which is used to initialize ProgressEvent computableLength
+        * xml/XMLHttpRequestUpload.cpp:
+        (WebCore::XMLHttpRequestUpload::XMLHttpRequestUpload):
+        (WebCore::XMLHttpRequestUpload::dispatchProgressEvent):
+        * xml/XMLHttpRequestUpload.h: introduced m_loaded, m_total and m_lengthComputable, similarly to XMLHttpRequestProgressEventThrottle
+
</ins><span class="cx"> 2014-01-08  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         TileController can fail to receive exposedRect from the drawing area if set at the wrong time
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -430,14 +430,14 @@
</span><span class="cx">     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(scriptExecutionContext(), this);
</span><span class="cx"> 
</span><span class="cx">     if (m_async || (m_state &lt;= OPENED || m_state == DONE))
</span><del>-        m_progressEventThrottle.dispatchReadyStateChangeEvent(XMLHttpRequestProgressEvent::create(eventNames().readystatechangeEvent), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent);
</del><ins>+        m_progressEventThrottle.dispatchReadyStateChangeEvent(Event::create(eventNames().readystatechangeEvent, false, false), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent);
</ins><span class="cx"> 
</span><span class="cx">     InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie);
</span><span class="cx">     if (m_state == DONE &amp;&amp; !m_error) {
</span><span class="cx">         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(scriptExecutionContext(), this);
</span><del>-        m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
</del><ins>+        m_progressEventThrottle.dispatchProgressEvent(eventNames().loadEvent);
</ins><span class="cx">         InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
</span><del>-        m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
</del><ins>+        m_progressEventThrottle.dispatchProgressEvent(eventNames().loadendEvent);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -765,10 +765,10 @@
</span><span class="cx">     // Also, only async requests support upload progress events.
</span><span class="cx">     bool uploadEvents = false;
</span><span class="cx">     if (m_async) {
</span><del>-        m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
</del><ins>+        m_progressEventThrottle.dispatchProgressEvent(eventNames().loadstartEvent);
</ins><span class="cx">         if (m_requestEntityBody &amp;&amp; m_upload) {
</span><span class="cx">             uploadEvents = m_upload-&gt;hasEventListeners();
</span><del>-            m_upload-&gt;dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
</del><ins>+            m_upload-&gt;dispatchProgressEvent(eventNames().loadstartEvent);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -862,12 +862,7 @@
</span><span class="cx">         m_state = UNSENT;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
-    if (!m_uploadComplete) {
-        m_uploadComplete = true;
-        if (m_upload &amp;&amp; m_uploadEventsAllowed)
-            m_upload-&gt;dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
-    }
</del><ins>+    dispatchErrorEvents(eventNames().abortEvent);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequest::internalAbort()
</span><span class="lines">@@ -928,24 +923,14 @@
</span><span class="cx"> void XMLHttpRequest::networkError()
</span><span class="cx"> {
</span><span class="cx">     genericError();
</span><del>-    if (!m_uploadComplete) {
-        m_uploadComplete = true;
-        if (m_upload &amp;&amp; m_uploadEventsAllowed)
-            m_upload-&gt;dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
-    }
-    m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
</del><ins>+    dispatchErrorEvents(eventNames().errorEvent);
</ins><span class="cx">     internalAbort();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequest::abortError()
</span><span class="cx"> {
</span><span class="cx">     genericError();
</span><del>-    if (!m_uploadComplete) {
-        m_uploadComplete = true;
-        if (m_upload &amp;&amp; m_uploadEventsAllowed)
-            m_upload-&gt;dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
-    }
-    m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
</del><ins>+    dispatchErrorEvents(eventNames().abortEvent);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequest::dropProtection()
</span><span class="lines">@@ -1179,12 +1164,13 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (m_uploadEventsAllowed)
</span><del>-        m_upload-&gt;dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, true, bytesSent, totalBytesToBeSent));
-
</del><ins>+        m_upload-&gt;dispatchThrottledProgressEvent(true, bytesSent, totalBytesToBeSent);
</ins><span class="cx">     if (bytesSent == totalBytesToBeSent &amp;&amp; !m_uploadComplete) {
</span><span class="cx">         m_uploadComplete = true;
</span><del>-        if (m_uploadEventsAllowed)
-            m_upload-&gt;dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
</del><ins>+        if (m_uploadEventsAllowed) {
+            m_upload-&gt;dispatchProgressEvent(eventNames().loadEvent);
+            m_upload-&gt;dispatchProgressEvent(eventNames().loadendEvent);
+        }
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1242,13 +1228,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!m_error) {
</span><del>-        long long expectedLength = m_response.expectedContentLength();
</del><span class="cx">         m_receivedLength += len;
</span><span class="cx"> 
</span><span class="cx">         if (m_async) {
</span><ins>+            long long expectedLength = m_response.expectedContentLength();
</ins><span class="cx">             bool lengthComputable = expectedLength &gt; 0 &amp;&amp; m_receivedLength &lt;= expectedLength;
</span><span class="cx">             unsigned long long total = lengthComputable ? expectedLength : 0;
</span><del>-            m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receivedLength, total);
</del><ins>+            m_progressEventThrottle.dispatchThrottledProgressEvent(lengthComputable, m_receivedLength, total);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_state != LOADING)
</span><span class="lines">@@ -1259,6 +1245,19 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void XMLHttpRequest::dispatchErrorEvents(const AtomicString&amp; type)
+{
+    if (!m_uploadComplete) {
+        m_uploadComplete = true;
+        if (m_upload &amp;&amp; m_uploadEventsAllowed) {
+            m_upload-&gt;dispatchProgressEvent(type);
+            m_upload-&gt;dispatchProgressEvent(eventNames().loadendEvent);
+        }
+    }
+    m_progressEventThrottle.dispatchProgressEvent(type);
+    m_progressEventThrottle.dispatchProgressEvent(eventNames().loadendEvent);
+}
+
</ins><span class="cx"> #if ENABLE(XHR_TIMEOUT)
</span><span class="cx"> void XMLHttpRequest::didTimeout()
</span><span class="cx"> {
</span><span class="lines">@@ -1280,12 +1279,7 @@
</span><span class="cx"> 
</span><span class="cx">     changeState(DONE);
</span><span class="cx"> 
</span><del>-    if (!m_uploadComplete) {
-        m_uploadComplete = true;
-        if (m_upload &amp;&amp; m_uploadEventsAllowed)
-            m_upload-&gt;dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().timeoutEvent));
-    }
-    m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().timeoutEvent));
</del><ins>+    dispatchErrorEvents(eventNames().timeoutEvent);
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.h        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -208,6 +208,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool shouldDecodeResponse() const { return m_responseTypeCode &lt; FirstBinaryResponseType; }
</span><span class="cx"> 
</span><ins>+    void dispatchErrorEvents(const AtomicString&amp;);
+
</ins><span class="cx">     std::unique_ptr&lt;XMLHttpRequestUpload&gt; m_upload;
</span><span class="cx"> 
</span><span class="cx">     URL m_url;
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestProgressEventThrottlecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -36,6 +36,8 @@
</span><span class="cx"> 
</span><span class="cx"> XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target)
</span><span class="cx">     : m_target(target)
</span><ins>+    , m_hasThrottledProgressEvent(false)
+    , m_lengthComputable(false)
</ins><span class="cx">     , m_loaded(0)
</span><span class="cx">     , m_total(0)
</span><span class="cx">     , m_deferEvents(false)
</span><span class="lines">@@ -48,8 +50,12 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
</del><ins>+void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
</ins><span class="cx"> {
</span><ins>+    m_lengthComputable = lengthComputable;
+    m_loaded = loaded;
+    m_total = total;
+    
</ins><span class="cx">     if (m_deferEvents) {
</span><span class="cx">         // Only store the latest progress event while suspended.
</span><span class="cx">         m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total);
</span><span class="lines">@@ -66,13 +72,12 @@
</span><span class="cx"> 
</span><span class="cx">         dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
</span><span class="cx">         startRepeating(minimumProgressEventDispatchingIntervalInSeconds);
</span><ins>+        m_hasThrottledProgressEvent = false;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // The timer is already active so minimumProgressEventDispatchingIntervalInSeconds is the least frequent event.
</span><del>-    m_lengthComputable = lengthComputable;
-    m_loaded = loaded;
-    m_total = total;
</del><ins>+    m_hasThrottledProgressEvent = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(PassRefPtr&lt;Event&gt; event, ProgressEventAction progressEventAction)
</span><span class="lines">@@ -96,12 +101,17 @@
</span><span class="cx">         m_target-&gt;dispatchEvent(event);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void XMLHttpRequestProgressEventThrottle::dispatchEventAndLoadEnd(PassRefPtr&lt;Event&gt; event)
</del><ins>+void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicString &amp;type)
</ins><span class="cx"> {
</span><del>-    ASSERT(event-&gt;type() == eventNames().loadEvent || event-&gt;type() == eventNames().abortEvent || event-&gt;type() == eventNames().errorEvent || event-&gt;type() == eventNames().timeoutEvent);
</del><ins>+    ASSERT(type == eventNames().loadEvent || type == eventNames().loadstartEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent);
</ins><span class="cx"> 
</span><del>-    dispatchEvent(event);
-    dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
</del><ins>+    if (type == eventNames().loadstartEvent) {
+        m_lengthComputable = false;
+        m_loaded = 0;
+        m_total = 0;
+    }
+
+    dispatchEvent(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequestProgressEventThrottle::flushProgressEvent()
</span><span class="lines">@@ -115,10 +125,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (!hasEventToDispatch())
</span><span class="cx">         return;
</span><del>-
</del><span class="cx">     PassRefPtr&lt;Event&gt; event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
</span><del>-    m_loaded = 0;
-    m_total = 0;
</del><ins>+    m_hasThrottledProgressEvent = false;
</ins><span class="cx"> 
</span><span class="cx">     // We stop the timer as this is called when no more events are supposed to occur.
</span><span class="cx">     stop();
</span><span class="lines">@@ -160,13 +168,12 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
</span><del>-    m_total = 0;
-    m_loaded = 0;
</del><ins>+    m_hasThrottledProgressEvent = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const
</span><span class="cx"> {
</span><del>-    return (m_total || m_loaded) &amp;&amp; isActive();
</del><ins>+    return m_hasThrottledProgressEvent &amp;&amp; isActive();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void XMLHttpRequestProgressEventThrottle::suspend()
</span><span class="lines">@@ -187,8 +194,7 @@
</span><span class="cx">     // just defer it.
</span><span class="cx">     if (hasEventToDispatch()) {
</span><span class="cx">         m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
</span><del>-        m_total = 0;
-        m_loaded = 0;
</del><ins>+        m_hasThrottledProgressEvent = false;
</ins><span class="cx">     }
</span><span class="cx">     stop();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestProgressEventThrottleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;Timer.h&quot;
</span><span class="cx"> #include &quot;wtf/PassRefPtr.h&quot;
</span><span class="cx"> #include &quot;wtf/Vector.h&quot;
</span><ins>+#include &lt;wtf/Forward.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -48,10 +49,10 @@
</span><span class="cx">     explicit XMLHttpRequestProgressEventThrottle(EventTarget*);
</span><span class="cx">     virtual ~XMLHttpRequestProgressEventThrottle();
</span><span class="cx"> 
</span><del>-    void dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
</del><ins>+    void dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
</ins><span class="cx">     void dispatchReadyStateChangeEvent(PassRefPtr&lt;Event&gt;, ProgressEventAction = DoNotFlushProgressEvent);
</span><span class="cx">     void dispatchEvent(PassRefPtr&lt;Event&gt;);
</span><del>-    void dispatchEventAndLoadEnd(PassRefPtr&lt;Event&gt;);
</del><ins>+    void dispatchProgressEvent(const AtomicString&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void suspend();
</span><span class="cx">     void resume();
</span><span class="lines">@@ -68,6 +69,7 @@
</span><span class="cx">     // Weak pointer to our XMLHttpRequest object as it is the one holding us.
</span><span class="cx">     EventTarget* m_target;
</span><span class="cx"> 
</span><ins>+    bool m_hasThrottledProgressEvent;
</ins><span class="cx">     bool m_lengthComputable;
</span><span class="cx">     unsigned long long m_loaded;
</span><span class="cx">     unsigned long long m_total;
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestUploadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequestUpload.cpp (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequestUpload.cpp        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/xml/XMLHttpRequestUpload.cpp        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -36,17 +36,33 @@
</span><span class="cx"> 
</span><span class="cx"> XMLHttpRequestUpload::XMLHttpRequestUpload(XMLHttpRequest* xmlHttpRequest)
</span><span class="cx">     : m_xmlHttpRequest(xmlHttpRequest)
</span><ins>+    , m_lengthComputable(false)
+    , m_loaded(0)
+    , m_total(0)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void XMLHttpRequestUpload::dispatchEventAndLoadEnd(PassRefPtr&lt;Event&gt; event)
</del><ins>+void XMLHttpRequestUpload::dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
</ins><span class="cx"> {
</span><del>-    ASSERT(event-&gt;type() == eventNames().loadEvent || event-&gt;type() == eventNames().abortEvent || event-&gt;type() == eventNames().errorEvent || event-&gt;type() == eventNames().timeoutEvent);
</del><ins>+    m_lengthComputable = lengthComputable;
+    m_loaded = loaded;
+    m_total = total;
</ins><span class="cx"> 
</span><del>-    dispatchEvent(event);
-    dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
</del><ins>+    dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void XMLHttpRequestUpload::dispatchProgressEvent(const AtomicString &amp;type)
+{
+    ASSERT(type == eventNames().loadEvent || type == eventNames().loadstartEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent);
</ins><span class="cx"> 
</span><ins>+    if (type == eventNames().loadstartEvent) {
+        m_lengthComputable = false;
+        m_loaded = 0;
+        m_total = 0;
+    }
</ins><span class="cx"> 
</span><ins>+    dispatchEvent(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));
+}
+
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestUploadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequestUpload.h (161531 => 161532)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequestUpload.h        2014-01-09 01:55:32 UTC (rev 161531)
+++ trunk/Source/WebCore/xml/XMLHttpRequestUpload.h        2014-01-09 02:11:59 UTC (rev 161532)
</span><span class="lines">@@ -55,13 +55,17 @@
</span><span class="cx">         DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
</span><span class="cx">         DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
</span><span class="cx"> 
</span><del>-        void dispatchEventAndLoadEnd(PassRefPtr&lt;Event&gt;);
</del><ins>+        void dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
+        void dispatchProgressEvent(const AtomicString &amp;type);
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         virtual void refEventTarget() OVERRIDE FINAL { ref(); }
</span><span class="cx">         virtual void derefEventTarget() OVERRIDE FINAL { deref(); }
</span><span class="cx"> 
</span><span class="cx">         XMLHttpRequest* m_xmlHttpRequest;
</span><ins>+        bool m_lengthComputable;
+        unsigned long long m_loaded;
+        unsigned long long m_total;
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>

</body>
</html>