<!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>[189445] 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/189445">189445</a></dd>
<dt>Author</dt> <dd>youenn.fablet@crf.canon.fr</dd>
<dt>Date</dt> <dd>2015-09-06 11:40:21 -0700 (Sun, 06 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>XHR2 timeout property should allow late updates
https://bugs.webkit.org/show_bug.cgi?id=98156

Reviewed by Darin Adler.

Source/WebCore:

Adding a timer within XMLHttpRequest to handle timeouts for asynchronous requests.
This allows easy update of the timeout even after request is sent.
Timeout is still handled by the network backend for synchronous requests (Web worker context).

Covered by updated tests.

* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::XMLHttpRequest): Adding timeout timer initialization.
(WebCore::XMLHttpRequest::setTimeout): Updating timeout timer state if request is sent.
(WebCore::XMLHttpRequest::createRequest): Starting timeout timer if needed.
(WebCore::XMLHttpRequest::internalAbort): Stopping timeout timer if needed.
(WebCore::XMLHttpRequest::didFail): Adding comment.
(WebCore::XMLHttpRequest::didFinishLoading): Stopping timeout timer if needed.
* xml/XMLHttpRequest.h:

LayoutTests:

Activating test checking that timeout can be updated after request is sent.

* http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides-expected.txt:
* http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.js:
* http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overrides-expected.txt:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequesttimeoutxmlhttprequesttimeoutoverridesexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequesttimeoutxmlhttprequesttimeoutoverridesjs">trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.js</a></li>
<li><a href="#trunkLayoutTestshttptestsxmlhttprequesttimeoutxmlhttprequesttimeoutworkeroverridesexpectedtxt">trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overrides-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="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/LayoutTests/ChangeLog        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2015-09-06  Youenn Fablet  &lt;youenn.fablet@crf.canon.fr&gt;
+
+        XHR2 timeout property should allow late updates
+        https://bugs.webkit.org/show_bug.cgi?id=98156
+
+        Reviewed by Darin Adler.
+
+        Activating test checking that timeout can be updated after request is sent.
+
+        * http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides-expected.txt:
+        * http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.js:
+        * http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overrides-expected.txt:
+
</ins><span class="cx"> 2015-09-04  Jon Honeycutt  &lt;jhoneycutt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Import a couple of Chromium accesskey tests.
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequesttimeoutxmlhttprequesttimeoutoverridesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides-expected.txt (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides-expected.txt        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides-expected.txt        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -5,4 +5,5 @@
</span><span class="cx"> 
</span><span class="cx"> PASS XHR2 Timeout Property Tests 
</span><span class="cx"> PASS XHR2 Timeout Property Tests 1 
</span><ins>+PASS XHR2 Timeout Property Tests 2 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequesttimeoutxmlhttprequesttimeoutoverridesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.js (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.js        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.js        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -2,5 +2,5 @@
</span><span class="cx">   importScripts(&quot;xmlhttprequest-timeout.js&quot;);
</span><span class="cx"> 
</span><span class="cx"> runTestRequests([ new RequestTracker(true, &quot;timeout disabled after initially set&quot;, TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, 0),
</span><del>-                  // new RequestTracker(true, &quot;timeout overrides load after a delay&quot;, TIME_NORMAL_LOAD, TIME_DELAY, TIME_REGULAR_TIMEOUT),
</del><ins>+                  new RequestTracker(true, &quot;timeout overrides load after a delay&quot;, TIME_NORMAL_LOAD, TIME_DELAY, TIME_REGULAR_TIMEOUT),
</ins><span class="cx">                   new RequestTracker(true, &quot;timeout enabled after initially disabled&quot;, 0, TIME_REGULAR_TIMEOUT, TIME_NORMAL_LOAD) ]);
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsxmlhttprequesttimeoutxmlhttprequesttimeoutworkeroverridesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overrides-expected.txt (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overrides-expected.txt        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overrides-expected.txt        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -5,4 +5,5 @@
</span><span class="cx"> 
</span><span class="cx"> PASS XHR2 Timeout Property Tests in Worker 
</span><span class="cx"> PASS XHR2 Timeout Property Tests in Worker 1 
</span><ins>+PASS XHR2 Timeout Property Tests in Worker 2 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/Source/WebCore/ChangeLog        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2015-09-06  Youenn Fablet  &lt;youenn.fablet@crf.canon.fr&gt;
+
+        XHR2 timeout property should allow late updates
+        https://bugs.webkit.org/show_bug.cgi?id=98156
+
+        Reviewed by Darin Adler.
+
+        Adding a timer within XMLHttpRequest to handle timeouts for asynchronous requests.
+        This allows easy update of the timeout even after request is sent.
+        Timeout is still handled by the network backend for synchronous requests (Web worker context).
+
+        Covered by updated tests.
+
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::XMLHttpRequest): Adding timeout timer initialization.
+        (WebCore::XMLHttpRequest::setTimeout): Updating timeout timer state if request is sent.
+        (WebCore::XMLHttpRequest::createRequest): Starting timeout timer if needed.
+        (WebCore::XMLHttpRequest::internalAbort): Stopping timeout timer if needed.
+        (WebCore::XMLHttpRequest::didFail): Adding comment.
+        (WebCore::XMLHttpRequest::didFinishLoading): Stopping timeout timer if needed.
+        * xml/XMLHttpRequest.h:
+
</ins><span class="cx"> 2015-09-05  Jaehun Lim  &lt;ljaehun.lim@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove unused macros from StyleResolver.cpp
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -120,9 +120,6 @@
</span><span class="cx">     : ActiveDOMObject(&amp;context)
</span><span class="cx">     , m_async(true)
</span><span class="cx">     , m_includeCredentials(false)
</span><del>-#if ENABLE(XHR_TIMEOUT)
-    , m_timeoutMilliseconds(0)
-#endif
</del><span class="cx">     , m_state(UNSENT)
</span><span class="cx">     , m_createdDocument(false)
</span><span class="cx">     , m_error(false)
</span><span class="lines">@@ -138,6 +135,9 @@
</span><span class="cx">     , m_responseCacheIsValid(false)
</span><span class="cx">     , m_resumeTimer(*this, &amp;XMLHttpRequest::resumeTimerFired)
</span><span class="cx">     , m_dispatchErrorOnResuming(false)
</span><ins>+#if ENABLE(XHR_TIMEOUT)
+    , m_timeoutTimer(*this, &amp;XMLHttpRequest::didTimeout)
+#endif
</ins><span class="cx"> {
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     xmlHttpRequestCounter.increment();
</span><span class="lines">@@ -272,16 +272,22 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(XHR_TIMEOUT)
</span><del>-void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionCode&amp; ec)
</del><ins>+void XMLHttpRequest::setTimeout(unsigned timeout, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    // FIXME: Need to trigger or update the timeout Timer here, if needed. http://webkit.org/b/98156
-    // XHR2 spec, 4.7.3. &quot;This implies that the timeout attribute can be set while fetching is in progress. If that occurs it will still be measured relative to the start of fetching.&quot;
</del><span class="cx">     if (scriptExecutionContext()-&gt;isDocument() &amp;&amp; !m_async) {
</span><span class="cx">         logConsoleError(scriptExecutionContext(), &quot;XMLHttpRequest.timeout cannot be set for synchronous HTTP(S) requests made from the window context.&quot;);
</span><span class="cx">         ec = INVALID_ACCESS_ERR;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     m_timeoutMilliseconds = timeout;
</span><ins>+    if (!m_timeoutTimer.isActive())
+        return;
+    if (!m_timeoutMilliseconds) {
+        m_timeoutTimer.stop();
+        return;
+    }
+    std::chrono::duration&lt;double&gt; interval = std::chrono::milliseconds { m_timeoutMilliseconds } - (std::chrono::steady_clock::now() - m_sendingTime);
+    m_timeoutTimer.startOneShot(std::max(0.0, interval.count()));
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -767,8 +773,14 @@
</span><span class="cx">     options.initiator = cachedResourceRequestInitiators().xmlhttprequest;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(XHR_TIMEOUT)
</span><del>-    if (m_timeoutMilliseconds)
-        request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0);
</del><ins>+    if (m_timeoutMilliseconds) {
+        if (!m_async)
+            request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0);
+        else {
+            m_sendingTime = std::chrono::steady_clock::now();
+            m_timeoutTimer.startOneShot(std::chrono::milliseconds { m_timeoutMilliseconds });
+        }
+    }
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     m_exceptionCode = 0;
</span><span class="lines">@@ -835,6 +847,11 @@
</span><span class="cx"> 
</span><span class="cx">     m_decoder = nullptr;
</span><span class="cx"> 
</span><ins>+#if ENABLE(XHR_TIMEOUT)
+    if (m_timeoutTimer.isActive())
+        m_timeoutTimer.stop();
+#endif
+
</ins><span class="cx">     if (!m_loader)
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="lines">@@ -1078,6 +1095,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(XHR_TIMEOUT)
</span><ins>+    // In case of worker sync timeouts.
</ins><span class="cx">     if (error.isTimeout()) {
</span><span class="cx">         didTimeout();
</span><span class="cx">         return;
</span><span class="lines">@@ -1119,6 +1137,11 @@
</span><span class="cx">     m_responseEncoding = String();
</span><span class="cx">     m_decoder = nullptr;
</span><span class="cx"> 
</span><ins>+#if ENABLE(XHR_TIMEOUT)
+    if (m_timeoutTimer.isActive())
+        m_timeoutTimer.stop();
+#endif
+
</ins><span class="cx">     if (hadLoader)
</span><span class="cx">         dropProtection();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorexmlXMLHttpRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (189444 => 189445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/XMLHttpRequest.h        2015-09-06 14:38:12 UTC (rev 189444)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h        2015-09-06 18:40:21 UTC (rev 189445)
</span><span class="lines">@@ -114,8 +114,8 @@
</span><span class="cx">     Blob* responseBlob();
</span><span class="cx">     Blob* optionalResponseBlob() const { return m_responseBlob.get(); }
</span><span class="cx"> #if ENABLE(XHR_TIMEOUT)
</span><del>-    unsigned long timeout() const { return m_timeoutMilliseconds; }
-    void setTimeout(unsigned long timeout, ExceptionCode&amp;);
</del><ins>+    unsigned timeout() const { return m_timeoutMilliseconds; }
+    void setTimeout(unsigned timeout, ExceptionCode&amp;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     bool responseCacheIsValid() const { return m_responseCacheIsValid; }
</span><span class="lines">@@ -216,9 +216,6 @@
</span><span class="cx">     String m_mimeTypeOverride;
</span><span class="cx">     bool m_async;
</span><span class="cx">     bool m_includeCredentials;
</span><del>-#if ENABLE(XHR_TIMEOUT)
-    unsigned long m_timeoutMilliseconds;
-#endif
</del><span class="cx">     RefPtr&lt;Blob&gt; m_responseBlob;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;ThreadableLoader&gt; m_loader;
</span><span class="lines">@@ -259,6 +256,12 @@
</span><span class="cx"> 
</span><span class="cx">     Timer m_resumeTimer;
</span><span class="cx">     bool m_dispatchErrorOnResuming;
</span><ins>+
+#if ENABLE(XHR_TIMEOUT)
+    unsigned m_timeoutMilliseconds { 0 };
+    std::chrono::steady_clock::time_point m_sendingTime;
+    Timer m_timeoutTimer;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>

</body>
</html>