<!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>[180934] 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/180934">180934</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2015-03-03 07:58:47 -0800 (Tue, 03 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make AudioContext suspendable when it is not rendering
https://bugs.webkit.org/show_bug.cgi?id=142210
&lt;rdar://problem/19923085&gt;

Reviewed by Eric Carlson.

Source/WebCore:

Make AudioContext suspendable when it is not rendering to increase the
likelihood of entering the PageCache for pages using WebAudio.

This patch adds a state member to AudioContext with 3 possible states:
Suspended / Running / Closed, as defined in the specification:
http://webaudio.github.io/web-audio-api/#widl-AudioContext-state

This state is used to decide if we can suspend the page or not. We
can safely suspend if the AudioContext's state is suspended (did not
start rendering) or closed (Stopped rendering).

Note that this patch does not expose the AudioContext's state to the
Web yet, even though it is exposed in the latest specification.

Tests: fast/history/page-cache-closed-audiocontext.html
       fast/history/page-cache-running-audiocontext.html
       fast/history/page-cache-suspended-audiocontext.html

* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::AudioContext):
(WebCore::AudioContext::uninitialize):
(WebCore::AudioContext::canSuspend):
(WebCore::AudioContext::startRendering):
(WebCore::AudioContext::fireCompletionEvent):
* Modules/webaudio/AudioContext.h:

LayoutTests:

Add layout tests to check cases where an AudioContext should or should
not prevent pages from entering the page cache.

* fast/history/page-cache-closed-audiocontext-expected.txt: Added.
* fast/history/page-cache-closed-audiocontext.html: Added.
* fast/history/page-cache-running-audiocontext-expected.txt: Added.
* fast/history/page-cache-running-audiocontext.html: Added.
* fast/history/page-cache-suspended-audiocontext-expected.txt: Added.
* fast/history/page-cache-suspended-audiocontext.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsplatformwinTestExpectations">trunk/LayoutTests/platform/win/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioContextcpp">trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioContexth">trunk/Source/WebCore/Modules/webaudio/AudioContext.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasthistorypagecacheclosedaudiocontextexpectedtxt">trunk/LayoutTests/fast/history/page-cache-closed-audiocontext-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthistorypagecacheclosedaudiocontexthtml">trunk/LayoutTests/fast/history/page-cache-closed-audiocontext.html</a></li>
<li><a href="#trunkLayoutTestsfasthistorypagecacherunningaudiocontextexpectedtxt">trunk/LayoutTests/fast/history/page-cache-running-audiocontext-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthistorypagecacherunningaudiocontexthtml">trunk/LayoutTests/fast/history/page-cache-running-audiocontext.html</a></li>
<li><a href="#trunkLayoutTestsfasthistorypagecachesuspendedaudiocontextexpectedtxt">trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthistorypagecachesuspendedaudiocontexthtml">trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (180933 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-03-03 15:10:34 UTC (rev 180933)
+++ trunk/LayoutTests/ChangeLog        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-03-03  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Make AudioContext suspendable when it is not rendering
+        https://bugs.webkit.org/show_bug.cgi?id=142210
+        &lt;rdar://problem/19923085&gt;
+
+        Reviewed by Eric Carlson.
+
+        Add layout tests to check cases where an AudioContext should or should
+        not prevent pages from entering the page cache.
+
+        * fast/history/page-cache-closed-audiocontext-expected.txt: Added.
+        * fast/history/page-cache-closed-audiocontext.html: Added.
+        * fast/history/page-cache-running-audiocontext-expected.txt: Added.
+        * fast/history/page-cache-running-audiocontext.html: Added.
+        * fast/history/page-cache-suspended-audiocontext-expected.txt: Added.
+        * fast/history/page-cache-suspended-audiocontext.html: Added.
+
</ins><span class="cx"> 2015-03-02  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Gardening: skipping inspector/timeline tests since they are still flaky.
</span></span></pre></div>
<a id="trunkLayoutTestsfasthistorypagecacheclosedaudiocontextexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/history/page-cache-closed-audiocontext-expected.txt (0 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/history/page-cache-closed-audiocontext-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-closed-audiocontext-expected.txt        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+Tests that a page with a closed AudioContext goes into the page cache.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+pageshow - not from cache
+pagehide - entering cache
+pageshow - from cache
+PASS Page did enter and was restored from the page cache
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthistorypagecacheclosedaudiocontexthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/history/page-cache-closed-audiocontext.html (0 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/history/page-cache-closed-audiocontext.html                                (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-closed-audiocontext.html        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../webaudio/resources/buffer-loader.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+description('Tests that a page with a closed AudioContext goes into the page cache.');
+window.jsTestIsAsync = true;
+
+var sampleRate = 44100.0;
+var lengthInSeconds = 2;
+
+if (window.testRunner)
+    testRunner.overridePreference(&quot;WebKitUsesPageCachePreferenceKey&quot;, 1);
+
+window.addEventListener(&quot;pageshow&quot;, function(event) {
+    debug(&quot;pageshow - &quot; + (event.persisted ? &quot;&quot; : &quot;not &quot;) + &quot;from cache&quot;);
+
+    if (event.persisted) {
+        testPassed(&quot;Page did enter and was restored from the page cache&quot;);
+        finishJSTest();
+    }
+}, false);
+
+window.addEventListener(&quot;pagehide&quot;, function(event) {
+    debug(&quot;pagehide - &quot; + (event.persisted ? &quot;&quot; : &quot;not &quot;) + &quot;entering cache&quot;);
+    if (!event.persisted) {
+        testFailed(&quot;Page did not enter the page cache.&quot;);
+        finishJSTest();
+    }
+}, false);
+
+window.addEventListener('load', function() {
+    audioContext = new webkitOfflineAudioContext(2, sampleRate * lengthInSeconds, sampleRate);
+    bufferLoader = new BufferLoader(
+        audioContext,
+        [ &quot;../../webaudio/resources/hyper-reality/br-jam-loop.wav&quot;, ],
+        finishedLoading
+    );
+    bufferLoader.load();
+}, false);
+
+function finishedLoading(bufferList)
+{
+    var bufferSource = audioContext.createBufferSource();
+    bufferSource.buffer = bufferList[0];
+
+    bufferSource.connect(audioContext.destination);
+    bufferSource.start(0);
+
+    audioContext.oncomplete = finishedPlaying;
+    audioContext.startRendering();    
+}
+
+function finishedPlaying()
+{
+    // The OfflineAudioContext should now be in 'closed' state since the completion event was fired.
+    // The context should thus be suspendable and not prevent the page from entering PageCache.
+    setTimeout(function() {
+        // Force a back navigation back to this page.
+        window.location.href = &quot;resources/page-cache-helper.html&quot;;
+    }, 0);
+}
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthistorypagecacherunningaudiocontextexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/history/page-cache-running-audiocontext-expected.txt (0 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/history/page-cache-running-audiocontext-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-running-audiocontext-expected.txt        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+Tests that a page with a running AudioContext does not go into the page cache.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+pageshow - not from cache
+PASS Page was not restored from page cache
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthistorypagecacherunningaudiocontexthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/history/page-cache-running-audiocontext.html (0 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/history/page-cache-running-audiocontext.html                                (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-running-audiocontext.html        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+description('Tests that a page with a running AudioContext does not go into the page cache.');
+window.jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.overridePreference(&quot;WebKitUsesPageCachePreferenceKey&quot;, 1);
+
+window.addEventListener(&quot;pageshow&quot;, function(event) {
+    debug(&quot;pageshow - &quot; + (event.persisted ? &quot;&quot; : &quot;not &quot;) + &quot;from cache&quot;);
+
+    if (!window.sessionStorage.page_cache_running_audiocontext_test_started)
+        return;
+
+    delete window.sessionStorage.page_cache_running_audiocontext_test_started;
+
+    if (event.persisted)
+        testFailed(&quot;Page did enter and was restored from the page cache&quot;);
+    else
+        testPassed(&quot;Page was not restored from page cache&quot;);
+
+    finishJSTest();
+}, false);
+
+window.addEventListener(&quot;pagehide&quot;, function(event) {
+    debug(&quot;pagehide - &quot; + (event.persisted ? &quot;&quot; : &quot;not &quot;) + &quot;entering cache&quot;);
+    if (event.persisted) {
+        testFailed(&quot;Page entered the page cache.&quot;);
+        finishJSTest();
+    }
+}, false);
+
+window.addEventListener('load', function() {
+    audioContext = new webkitAudioContext();
+
+    oscillator = audioContext.createOscillator();
+    oscillator.frequency.value = 300;
+    oscillator.type = 0;
+    oscillator.connect(audioContext.destination);
+    oscillator.start(0);
+
+    setTimeout(function() {
+        // Force a back navigation back to this page.
+        window.sessionStorage.page_cache_running_audiocontext_test_started = true;
+        window.location.href = &quot;resources/page-cache-helper.html&quot;;
+    }, 0);
+}, false);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthistorypagecachesuspendedaudiocontextexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext-expected.txt (0 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext-expected.txt        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+Tests that a page with a suspended AudioContext goes into the page cache.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+pageshow - not from cache
+pagehide - entering cache
+pageshow - from cache
+PASS Page did enter and was restored from the page cache
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthistorypagecachesuspendedaudiocontexthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext.html (0 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext.html                                (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-suspended-audiocontext.html        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+description('Tests that a page with a suspended AudioContext goes into the page cache.');
+window.jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.overridePreference(&quot;WebKitUsesPageCachePreferenceKey&quot;, 1);
+
+window.addEventListener(&quot;pageshow&quot;, function(event) {
+    debug(&quot;pageshow - &quot; + (event.persisted ? &quot;&quot; : &quot;not &quot;) + &quot;from cache&quot;);
+
+    if (event.persisted) {
+        testPassed(&quot;Page did enter and was restored from the page cache&quot;);
+        finishJSTest();
+    }
+}, false);
+
+window.addEventListener(&quot;pagehide&quot;, function(event) {
+    debug(&quot;pagehide - &quot; + (event.persisted ? &quot;&quot; : &quot;not &quot;) + &quot;entering cache&quot;);
+    if (!event.persisted) {
+        testFailed(&quot;Page did not enter the page cache.&quot;);
+        finishJSTest();
+    }
+}, false);
+
+window.addEventListener('load', function() {
+    // The newly constructed AudioContext is initially in suspended state.
+    audioContext = new webkitAudioContext();
+
+    // Needs to happen outside the onload handler so that a history item is created.
+    setTimeout(function() {
+        // Force a back navigation back to this page.
+        window.location.href = &quot;resources/page-cache-helper.html&quot;;
+    }, 0);
+}, false);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (180933 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/TestExpectations        2015-03-03 15:10:34 UTC (rev 180933)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -32,6 +32,12 @@
</span><span class="cx"> fast/history/page-cache-notification-non-suspendable.html
</span><span class="cx"> fast/history/page-cache-notification-suspendable.html
</span><span class="cx"> 
</span><ins>+# Web Audio tests are skipped on iOS for now.
+webaudio
+fast/history/page-cache-closed-audiocontext.html
+fast/history/page-cache-running-audiocontext.html
+fast/history/page-cache-suspended-audiocontext.html
+
</ins><span class="cx"> # Not supported on iOS
</span><span class="cx"> batterystatus
</span><span class="cx"> fast/mediastream
</span><span class="lines">@@ -42,7 +48,6 @@
</span><span class="cx"> proximity
</span><span class="cx"> touchadjustment
</span><span class="cx"> vibration
</span><del>-webaudio
</del><span class="cx"> 
</span><span class="cx"> # ENABLE(MEDIA_CAPTURE) is not enabled
</span><span class="cx"> fast/forms/file/file-input-capture.html
</span></span></pre></div>
<a id="trunkLayoutTestsplatformwinTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/win/TestExpectations (180933 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/win/TestExpectations        2015-03-03 15:10:34 UTC (rev 180933)
+++ trunk/LayoutTests/platform/win/TestExpectations        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -442,6 +442,9 @@
</span><span class="cx"> 
</span><span class="cx"> # TODO For now, Web Audio tests are disabled
</span><span class="cx"> webkit.org/b/86914 webaudio/ [ Skip ]
</span><ins>+webkit.org/b/86914 fast/history/page-cache-closed-audiocontext.html [ Skip ]
+webkit.org/b/86914 fast/history/page-cache-running-audiocontext.html [ Skip ]
+webkit.org/b/86914 fast/history/page-cache-suspended-audiocontext.html [ Skip ]
</ins><span class="cx"> 
</span><span class="cx"> # ENABLE(DRAGGABLE_REGION) is disabled
</span><span class="cx"> fast/css/draggable-region-parser.html [ Skip ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (180933 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-03-03 15:10:34 UTC (rev 180933)
+++ trunk/Source/WebCore/ChangeLog        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2015-03-03  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Make AudioContext suspendable when it is not rendering
+        https://bugs.webkit.org/show_bug.cgi?id=142210
+        &lt;rdar://problem/19923085&gt;
+
+        Reviewed by Eric Carlson.
+
+        Make AudioContext suspendable when it is not rendering to increase the
+        likelihood of entering the PageCache for pages using WebAudio.
+
+        This patch adds a state member to AudioContext with 3 possible states:
+        Suspended / Running / Closed, as defined in the specification:
+        http://webaudio.github.io/web-audio-api/#widl-AudioContext-state
+
+        This state is used to decide if we can suspend the page or not. We
+        can safely suspend if the AudioContext's state is suspended (did not
+        start rendering) or closed (Stopped rendering).
+
+        Note that this patch does not expose the AudioContext's state to the
+        Web yet, even though it is exposed in the latest specification.
+
+        Tests: fast/history/page-cache-closed-audiocontext.html
+               fast/history/page-cache-running-audiocontext.html
+               fast/history/page-cache-suspended-audiocontext.html
+
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::AudioContext):
+        (WebCore::AudioContext::uninitialize):
+        (WebCore::AudioContext::canSuspend):
+        (WebCore::AudioContext::startRendering):
+        (WebCore::AudioContext::fireCompletionEvent):
+        * Modules/webaudio/AudioContext.h:
+
</ins><span class="cx"> 2015-03-02  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [SOUP] Use SoupMessage::starting instead of SoupSession::request-started
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioContextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (180933 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp        2015-03-03 15:10:34 UTC (rev 180933)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -138,6 +138,7 @@
</span><span class="cx">     , m_isOfflineContext(false)
</span><span class="cx">     , m_activeSourceCount(0)
</span><span class="cx">     , m_restrictions(NoRestrictions)
</span><ins>+    , m_state(State::Suspended)
</ins><span class="cx"> {
</span><span class="cx">     constructCommon();
</span><span class="cx"> 
</span><span class="lines">@@ -161,6 +162,7 @@
</span><span class="cx">     , m_isOfflineContext(true)
</span><span class="cx">     , m_activeSourceCount(0)
</span><span class="cx">     , m_restrictions(NoRestrictions)
</span><ins>+    , m_state(State::Suspended)
</ins><span class="cx"> {
</span><span class="cx">     constructCommon();
</span><span class="cx"> 
</span><span class="lines">@@ -273,6 +275,9 @@
</span><span class="cx"> 
</span><span class="cx">         ASSERT(s_hardwareContextCount);
</span><span class="cx">         --s_hardwareContextCount;
</span><ins>+
+        // Offline contexts move to 'Closed' state when dispatching the completion event.
+        m_state = State::Closed;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Get rid of the sources which may still be playing.
</span><span class="lines">@@ -315,8 +320,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool AudioContext::canSuspend() const
</span><span class="cx"> {
</span><del>-    // FIXME: We should try and do better here.
-    return false;
</del><ins>+    // FIXME: We should be able to suspend while rendering as well with some more code.
+    return m_state == State::Suspended || m_state == State::Closed;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const char* AudioContext::activeDOMObjectName() const
</span><span class="lines">@@ -975,6 +980,7 @@
</span><span class="cx">             removeBehaviorRestriction(AudioContext::RequirePageConsentForAudioStartRestriction);
</span><span class="cx">     }
</span><span class="cx">     destination()-&gt;startRendering();
</span><ins>+    m_state = State::Running;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AudioContext::mediaCanStart()
</span><span class="lines">@@ -1005,6 +1011,7 @@
</span><span class="cx">         return;
</span><span class="cx">         
</span><span class="cx">     AudioBuffer* renderedBuffer = m_renderTarget.get();
</span><ins>+    m_state = State::Closed;
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(renderedBuffer);
</span><span class="cx">     if (!renderedBuffer)
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (180933 => 180934)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h        2015-03-03 15:10:34 UTC (rev 180933)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h        2015-03-03 15:58:47 UTC (rev 180934)
</span><span class="lines">@@ -363,6 +363,9 @@
</span><span class="cx">     std::atomic&lt;int&gt; m_activeSourceCount;
</span><span class="cx"> 
</span><span class="cx">     BehaviorRestrictions m_restrictions;
</span><ins>+
+    enum class State { Suspended, Running, Closed };
+    State m_state;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // WebCore
</span></span></pre>
</div>
</div>

</body>
</html>