<!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>[212311] 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/212311">212311</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2017-02-14 11:17:14 -0800 (Tue, 14 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Video elements with MediaSource objects set by srcObject are not cleared when srcObject is set to null
https://bugs.webkit.org/show_bug.cgi?id=168268

Reviewed by Eric Carlson.

Source/WebCore:

Test: fast/mediastream/MediaStream-MediaElement-setObject-null.html

Make the setSrcObject() operation compliant with the HTML spec. Since the specification defines
srcObject in terms of either a MediaSource, MediaStream, or Blob object, add the variant typedef
to HTMLMediaElement and move the definition out of the Modules/mediastream extension IDL and into
HTMLMediaElement.idl. Then bring the &quot;media elements load&quot; and &quot;resource selection&quot; algorithms up
to their most recent definitions in the HTML5 spec.

Drive-by fix: Allow the (admittedly weird) single-element-union type in IDL.

* CMakeLists.txt:
* DerivedSources.cpp:
* DerivedSources.make:
* Modules/mediastream/HTMLMediaElementMediaStream.cpp: Removed.
* Modules/mediastream/HTMLMediaElementMediaStream.h: Removed.
* Modules/mediastream/HTMLMediaElementMediaStream.idl: Removed.
* WebCore.xcodeproj/project.pbxproj:
* bindings/scripts/IDLParser.pm:
(parseUnionType):
* html/HTMLAudioElement.cpp:
(WebCore::HTMLAudioElement::createForJSConstructor):
* html/HTMLMediaElement.cpp:
(WebCore::actionName):
(WebCore::HTMLMediaElement::parseAttribute):
(WebCore::HTMLMediaElement::insertedInto):
(WebCore::HTMLMediaElement::scheduleDelayedAction):
(WebCore::HTMLMediaElement::scheduleNextSourceChild):
(WebCore::HTMLMediaElement::pendingActionTimerFired):
(WebCore::HTMLMediaElement::setSrcObject):
(WebCore::HTMLMediaElement::load):
(WebCore::HTMLMediaElement::prepareForLoad):
(WebCore::HTMLMediaElement::selectMediaResource):
(WebCore::HTMLMediaElement::loadResource):
(WebCore::HTMLMediaElement::playInternal):
(WebCore::HTMLMediaElement::pauseInternal):
(WebCore::HTMLMediaElement::sourceWasAdded):
(WebCore::HTMLMediaElement::clearMediaPlayer):
(WebCore::HTMLMediaElement::resume):
(WebCore::HTMLMediaElement::mediaCanStart):
(WebCore::HTMLMediaElement::createMediaPlayer):
(WebCore::HTMLMediaElement::loadInternal): Deleted.
* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::srcObject):
* html/HTMLMediaElement.idl:
* platform/ContentType.h:

LayoutTests:

* fast/mediastream/MediaStream-MediaElement-setObject-null-expected.txt: Added.
* fast/mediastream/MediaStream-MediaElement-setObject-null.html: Added.
* fast/mediastream/MediaStream-video-element-expected.txt:
* fast/mediastream/MediaStream-video-element-track-stop-expected.txt:
* fast/mediastream/MediaStream-video-element-track-stop.html:
* fast/mediastream/MediaStream-video-element.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaStreamvideoelementexpectedtxt">trunk/LayoutTests/fast/mediastream/MediaStream-video-element-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaStreamvideoelementtrackstopexpectedtxt">trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaStreamvideoelementtrackstophtml">trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop.html</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaStreamvideoelementhtml">trunk/LayoutTests/fast/mediastream/MediaStream-video-element.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcescpp">trunk/Source/WebCore/DerivedSources.cpp</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsIDLParserpm">trunk/Source/WebCore/bindings/scripts/IDLParser.pm</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLAudioElementcpp">trunk/Source/WebCore/html/HTMLAudioElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementh">trunk/Source/WebCore/html/HTMLMediaElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementidl">trunk/Source/WebCore/html/HTMLMediaElement.idl</a></li>
<li><a href="#trunkSourceWebCoreplatformContentTypeh">trunk/Source/WebCore/platform/ContentType.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastmediastreamMediaStreamMediaElementsetObjectnullexpectedtxt">trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaStreamMediaElementsetObjectnullhtml">trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null.html</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreModulesmediastreamHTMLMediaElementMediaStreamcpp">trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamHTMLMediaElementMediaStreamh">trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamHTMLMediaElementMediaStreamidl">trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/LayoutTests/ChangeLog        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2017-02-14  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Video elements with MediaSource objects set by srcObject are not cleared when srcObject is set to null
+        https://bugs.webkit.org/show_bug.cgi?id=168268
+
+        Reviewed by Eric Carlson.
+
+        * fast/mediastream/MediaStream-MediaElement-setObject-null-expected.txt: Added.
+        * fast/mediastream/MediaStream-MediaElement-setObject-null.html: Added.
+        * fast/mediastream/MediaStream-video-element-expected.txt:
+        * fast/mediastream/MediaStream-video-element-track-stop-expected.txt:
+        * fast/mediastream/MediaStream-video-element-track-stop.html:
+        * fast/mediastream/MediaStream-video-element.html:
+
</ins><span class="cx"> 2017-02-14  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [mac-wk1] LayoutTest media/modern-media-controls/forward-button/forward-button.html is a flaky timeout
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaStreamMediaElementsetObjectnullexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null-expected.txt (0 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null-expected.txt        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+PASS video.srcObject = stream did not throw exception.
+PASS video.duration is Number.POSITIVE_INFINITY
+PASS video.srcObject = null did not throw exception.
+PASS video.duration is Number.NaN
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaStreamMediaElementsetObjectnullhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null.html (0 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null.html                                (rev 0)
+++ trunk/LayoutTests/fast/mediastream/MediaStream-MediaElement-setObject-null.html        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/getUserMedia-helper.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+var video;
+var stream;
+
+function setStream(stream)
+{
+    window.stream = stream;
+        shouldNotThrow('video.srcObject = stream');
+    video.addEventListener('loadedmetadata', loadedMetadata);
+}
+
+function loadedMetadata(event)
+{
+    shouldBe('video.duration', 'Number.POSITIVE_INFINITY');
+    video.play().then(clearStream());
+}
+
+function clearStream()
+{
+    video.addEventListener('abort', abort);
+        shouldNotThrow('video.srcObject = null');
+}
+
+function abort()
+{
+    shouldBe('video.duration', 'Number.NaN');
+    finishJSTest();
+}
+
+function runTest()
+{
+    if (window.testRunner)
+        testRunner.setUserMediaPermission(true);
+
+    video = document.querySelector('#video');
+    navigator.mediaDevices.getUserMedia({ video: { }, audio: true })
+        .then(setStream)
+        .catch(defaultRejectOrCatch);
+}
+
+window.addEventListener('load', runTest);
+window.jsTestIsAsync = true;
+window.successfullyParsed = true;
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+&lt;video id=&quot;video&quot;&gt;&lt;/video&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaStreamvideoelementexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/MediaStream-video-element-expected.txt (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaStream-video-element-expected.txt        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/LayoutTests/fast/mediastream/MediaStream-video-element-expected.txt        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -24,7 +24,6 @@
</span><span class="cx"> PASS video.videoWidth is mediaStream.getVideoTracks()[0].getSettings().width
</span><span class="cx"> PASS video.videoHeight is mediaStream.getVideoTracks()[0].getSettings().height
</span><span class="cx"> PASS video.src.indexOf(&quot;blob:&quot;) is 0
</span><del>-PASS video.srcObject is mediaStream
</del><span class="cx"> 
</span><span class="cx"> **** check video tracks ****
</span><span class="cx"> PASS video.videoTracks.length is 1
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaStreamvideoelementtrackstopexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop-expected.txt (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop-expected.txt        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop-expected.txt        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -25,7 +25,6 @@
</span><span class="cx"> PASS video.videoWidth is mediaStream.getVideoTracks()[0].getSettings().width
</span><span class="cx"> PASS video.videoHeight is mediaStream.getVideoTracks()[0].getSettings().height
</span><span class="cx"> PASS video.src.indexOf(&quot;blob:&quot;) is 0
</span><del>-PASS video.srcObject is mediaStream
</del><span class="cx"> 
</span><span class="cx"> PASS video.videoTracks.length is 1
</span><span class="cx"> PASS video.videoTracks.selectedIndex is 0
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaStreamvideoelementtrackstophtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop.html (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop.html        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/LayoutTests/fast/mediastream/MediaStream-video-element-track-stop.html        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -63,7 +63,6 @@
</span><span class="cx">                 shouldBe('video.videoWidth', 'mediaStream.getVideoTracks()[0].getSettings().width');
</span><span class="cx">                 shouldBe('video.videoHeight', 'mediaStream.getVideoTracks()[0].getSettings().height');
</span><span class="cx">                 shouldBe('video.src.indexOf(&quot;blob:&quot;)', '0');
</span><del>-                shouldBe('video.srcObject', 'mediaStream');
</del><span class="cx">                 
</span><span class="cx">                 debug(&quot;&quot;);
</span><span class="cx">                 shouldBe('video.videoTracks.length', '1');
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaStreamvideoelementhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/MediaStream-video-element.html (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaStream-video-element.html        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/LayoutTests/fast/mediastream/MediaStream-video-element.html        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -59,8 +59,7 @@
</span><span class="cx">                 shouldBe('video.videoWidth', 'mediaStream.getVideoTracks()[0].getSettings().width');
</span><span class="cx">                 shouldBe('video.videoHeight', 'mediaStream.getVideoTracks()[0].getSettings().height');
</span><span class="cx">                 shouldBe('video.src.indexOf(&quot;blob:&quot;)', '0');
</span><del>-                shouldBe('video.srcObject', 'mediaStream');
-                
</del><ins>+
</ins><span class="cx">                 debug(&quot;&lt;br&gt;**** check video tracks ****&quot;);
</span><span class="cx">                 shouldBe('video.videoTracks.length', '1');
</span><span class="cx">                 shouldBe('video.videoTracks[0].id', 'mediaStream.getVideoTracks()[0].id');
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/CMakeLists.txt        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -211,7 +211,6 @@
</span><span class="cx"> 
</span><span class="cx">     Modules/mediastream/DOMURLMediaStream.idl
</span><span class="cx">     Modules/mediastream/DoubleRange.idl
</span><del>-    Modules/mediastream/HTMLMediaElementMediaStream.idl
</del><span class="cx">     Modules/mediastream/LongRange.idl
</span><span class="cx">     Modules/mediastream/MediaDeviceInfo.idl
</span><span class="cx">     Modules/mediastream/MediaDevices.idl
</span><span class="lines">@@ -896,7 +895,6 @@
</span><span class="cx">     Modules/mediasource/VideoPlaybackQuality.cpp
</span><span class="cx"> 
</span><span class="cx">     Modules/mediastream/DOMURLMediaStream.cpp
</span><del>-    Modules/mediastream/HTMLMediaElementMediaStream.cpp
</del><span class="cx">     Modules/mediastream/MediaConstraintsImpl.cpp
</span><span class="cx">     Modules/mediastream/MediaDeviceInfo.cpp
</span><span class="cx">     Modules/mediastream/MediaDevices.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/ChangeLog        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2017-02-14  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Video elements with MediaSource objects set by srcObject are not cleared when srcObject is set to null
+        https://bugs.webkit.org/show_bug.cgi?id=168268
+
+        Reviewed by Eric Carlson.
+
+        Test: fast/mediastream/MediaStream-MediaElement-setObject-null.html
+
+        Make the setSrcObject() operation compliant with the HTML spec. Since the specification defines
+        srcObject in terms of either a MediaSource, MediaStream, or Blob object, add the variant typedef
+        to HTMLMediaElement and move the definition out of the Modules/mediastream extension IDL and into
+        HTMLMediaElement.idl. Then bring the &quot;media elements load&quot; and &quot;resource selection&quot; algorithms up
+        to their most recent definitions in the HTML5 spec.
+
+        Drive-by fix: Allow the (admittedly weird) single-element-union type in IDL.
+
+        * CMakeLists.txt:
+        * DerivedSources.cpp:
+        * DerivedSources.make:
+        * Modules/mediastream/HTMLMediaElementMediaStream.cpp: Removed.
+        * Modules/mediastream/HTMLMediaElementMediaStream.h: Removed.
+        * Modules/mediastream/HTMLMediaElementMediaStream.idl: Removed.
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/scripts/IDLParser.pm:
+        (parseUnionType):
+        * html/HTMLAudioElement.cpp:
+        (WebCore::HTMLAudioElement::createForJSConstructor):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::actionName):
+        (WebCore::HTMLMediaElement::parseAttribute):
+        (WebCore::HTMLMediaElement::insertedInto):
+        (WebCore::HTMLMediaElement::scheduleDelayedAction):
+        (WebCore::HTMLMediaElement::scheduleNextSourceChild):
+        (WebCore::HTMLMediaElement::pendingActionTimerFired):
+        (WebCore::HTMLMediaElement::setSrcObject):
+        (WebCore::HTMLMediaElement::load):
+        (WebCore::HTMLMediaElement::prepareForLoad):
+        (WebCore::HTMLMediaElement::selectMediaResource):
+        (WebCore::HTMLMediaElement::loadResource):
+        (WebCore::HTMLMediaElement::playInternal):
+        (WebCore::HTMLMediaElement::pauseInternal):
+        (WebCore::HTMLMediaElement::sourceWasAdded):
+        (WebCore::HTMLMediaElement::clearMediaPlayer):
+        (WebCore::HTMLMediaElement::resume):
+        (WebCore::HTMLMediaElement::mediaCanStart):
+        (WebCore::HTMLMediaElement::createMediaPlayer):
+        (WebCore::HTMLMediaElement::loadInternal): Deleted.
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::srcObject):
+        * html/HTMLMediaElement.idl:
+        * platform/ContentType.h:
+
</ins><span class="cx"> 2017-02-14  Aakash Jain  &lt;aakash_jain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove unused WebThreadContextIsCurrent method from WebCoreThread.h
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.cpp (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.cpp        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/DerivedSources.cpp        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -263,7 +263,6 @@
</span><span class="cx"> #include &quot;JSHTMLMarqueeElement.cpp&quot;
</span><span class="cx"> #include &quot;JSHTMLMediaElement.cpp&quot;
</span><span class="cx"> #include &quot;JSHTMLMediaElementMediaSession.cpp&quot;
</span><del>-#include &quot;JSHTMLMediaElementMediaStream.cpp&quot;
</del><span class="cx"> #include &quot;JSHTMLMenuElement.cpp&quot;
</span><span class="cx"> #include &quot;JSHTMLMetaElement.cpp&quot;
</span><span class="cx"> #include &quot;JSHTMLMeterElement.cpp&quot;
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.make        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/DerivedSources.make        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -152,7 +152,6 @@
</span><span class="cx">     $(WebCore)/Modules/mediasource/VideoTrackMediaSource.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/DOMURLMediaStream.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/DoubleRange.idl \
</span><del>-    $(WebCore)/Modules/mediastream/HTMLMediaElementMediaStream.idl \
</del><span class="cx">     $(WebCore)/Modules/mediastream/LongRange.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/MediaDeviceInfo.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/MediaDevices.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamHTMLMediaElementMediaStreamcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.cpp (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.cpp        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.cpp        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -1,48 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include &quot;config.h&quot;
-#include &quot;HTMLMediaElementMediaStream.h&quot;
-
-#if ENABLE(MEDIA_STREAM) &amp;&amp; ENABLE(VIDEO)
-
-#include &quot;HTMLMediaElement.h&quot;
-#include &quot;MediaStream.h&quot;
-
-namespace WebCore {
-
-MediaStream* HTMLMediaElementMediaStream::srcObject(HTMLMediaElement&amp; mediaElement)
-{
-    return mediaElement.srcObject();
-}
-
-void HTMLMediaElementMediaStream::setSrcObject(ScriptExecutionContext&amp; context, HTMLMediaElement&amp; mediaElement, MediaStream* mediaStream)
-{
-    mediaElement.setSrcObject(context, mediaStream);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) &amp;&amp; ENABLE(VIDEO)
</del></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamHTMLMediaElementMediaStreamh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.h (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.h        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.h        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -1,44 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(MEDIA_STREAM) &amp;&amp; ENABLE(VIDEO)
-
-namespace WebCore {
-
-class HTMLMediaElement;
-class MediaStream;
-class ScriptExecutionContext;
-
-class HTMLMediaElementMediaStream {
-public:
-    static MediaStream* srcObject(HTMLMediaElement&amp;);
-    static void setSrcObject(ScriptExecutionContext&amp;, HTMLMediaElement&amp;, MediaStream*);
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) &amp;&amp; ENABLE(VIDEO)
</del></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamHTMLMediaElementMediaStreamidl"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.idl (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.idl        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/Modules/mediastream/HTMLMediaElementMediaStream.idl        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -1,31 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-[
-    Conditional=VIDEO&amp;MEDIA_STREAM,
-] partial interface HTMLMediaElement
-{
-    [SetterCallWith=ScriptExecutionContext] attribute MediaStream? srcObject;
-};
</del></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -162,7 +162,6 @@
</span><span class="cx">                 07707CB01E205EE300005BF7 /* AudioSourceObserverObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 07707CAF1E205EC400005BF7 /* AudioSourceObserverObjC.h */; };
</span><span class="cx">                 077664FC183E6B5C00133B92 /* JSQuickTimePluginReplacement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 077664FA183E6B5C00133B92 /* JSQuickTimePluginReplacement.cpp */; };
</span><span class="cx">                 077664FD183E6B5C00133B92 /* JSQuickTimePluginReplacement.h in Headers */ = {isa = PBXBuildFile; fileRef = 077664FB183E6B5C00133B92 /* JSQuickTimePluginReplacement.h */; };
</span><del>-                0779BF0D18453168000B6AE7 /* HTMLMediaElementMediaStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0779BF0A18453168000B6AE7 /* HTMLMediaElementMediaStream.cpp */; };
</del><span class="cx">                 0779BF0E18453168000B6AE7 /* HTMLMediaElementMediaStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 0779BF0B18453168000B6AE7 /* HTMLMediaElementMediaStream.h */; };
</span><span class="cx">                 077AF14018F4AE400001ED61 /* SerializedPlatformRepresentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 077AF13E18F4AE400001ED61 /* SerializedPlatformRepresentation.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 077AF14318F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */; };
</span><span class="lines">@@ -7290,7 +7289,6 @@
</span><span class="cx">                 07707CB11E20649C00005BF7 /* AudioCaptureSourceProviderObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioCaptureSourceProviderObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 077664FA183E6B5C00133B92 /* JSQuickTimePluginReplacement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSQuickTimePluginReplacement.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 077664FB183E6B5C00133B92 /* JSQuickTimePluginReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQuickTimePluginReplacement.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0779BF0A18453168000B6AE7 /* HTMLMediaElementMediaStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLMediaElementMediaStream.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 0779BF0B18453168000B6AE7 /* HTMLMediaElementMediaStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLMediaElementMediaStream.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0779BF0C18453168000B6AE7 /* HTMLMediaElementMediaStream.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLMediaElementMediaStream.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 077AF13E18F4AE400001ED61 /* SerializedPlatformRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SerializedPlatformRepresentation.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15297,7 +15295,6 @@
</span><span class="cx">                                 073794EE19EE364200E5A045 /* DOMURLMediaStream.idl */,
</span><span class="cx">                                 93A806111E03B51C008A1F26 /* DoubleRange.h */,
</span><span class="cx">                                 93A806121E03B51C008A1F26 /* DoubleRange.idl */,
</span><del>-                                0779BF0A18453168000B6AE7 /* HTMLMediaElementMediaStream.cpp */,
</del><span class="cx">                                 0779BF0B18453168000B6AE7 /* HTMLMediaElementMediaStream.h */,
</span><span class="cx">                                 0779BF0C18453168000B6AE7 /* HTMLMediaElementMediaStream.idl */,
</span><span class="cx">                                 93A806131E03B51C008A1F26 /* LongRange.h */,
</span><span class="lines">@@ -30044,7 +30041,6 @@
</span><span class="cx">                                 A8EA7CAC0A192B9C00A8EF5F /* HTMLMarqueeElement.cpp in Sources */,
</span><span class="cx">                                 E44613A40CD6331000FADA75 /* HTMLMediaElement.cpp in Sources */,
</span><span class="cx">                                 C968B2E81B1E778100EF1F81 /* HTMLMediaElementMediaSession.cpp in Sources */,
</span><del>-                                0779BF0D18453168000B6AE7 /* HTMLMediaElementMediaStream.cpp in Sources */,
</del><span class="cx">                                 A8EA79F80A1916DF00A8EF5F /* HTMLMenuElement.cpp in Sources */,
</span><span class="cx">                                 2BE8E2C912A58A0100FAD550 /* HTMLMetaCharsetParser.cpp in Sources */,
</span><span class="cx">                                 A871DC270A15205700B12A68 /* HTMLMetaElement.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsIDLParserpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/IDLParser.pm (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/IDLParser.pm        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/bindings/scripts/IDLParser.pm        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -2018,10 +2018,6 @@
</span><span class="cx">         $self-&gt;assertTokenValue($self-&gt;getToken(), &quot;(&quot;, __LINE__);
</span><span class="cx">         
</span><span class="cx">         push(@{$unionType-&gt;subtypes}, $self-&gt;parseUnionMemberType());
</span><del>-        
-        $self-&gt;assertTokenValue($self-&gt;getToken(), &quot;or&quot;, __LINE__);
-        
-        push(@{$unionType-&gt;subtypes}, $self-&gt;parseUnionMemberType());
</del><span class="cx">         push(@{$unionType-&gt;subtypes}, $self-&gt;parseUnionMemberTypes());
</span><span class="cx">         
</span><span class="cx">         $self-&gt;assertTokenValue($self-&gt;getToken(), &quot;)&quot;, __LINE__);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLAudioElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLAudioElement.cpp (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLAudioElement.cpp        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/html/HTMLAudioElement.cpp        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -50,10 +50,8 @@
</span><span class="cx"> {
</span><span class="cx">     Ref&lt;HTMLAudioElement&gt; audio = adoptRef(*new HTMLAudioElement(audioTag, document, false));
</span><span class="cx">     audio-&gt;setPreload(&quot;auto&quot;);
</span><del>-    if (!src.isNull()) {
</del><ins>+    if (!src.isNull())
</ins><span class="cx">         audio-&gt;setSrc(src);
</span><del>-        audio-&gt;scheduleDelayedAction(HTMLMediaElement::LoadMediaResource);
-    }
</del><span class="cx">     audio-&gt;suspendIfNeeded();
</span><span class="cx">     return audio;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;ApplicationCacheHost.h&quot;
</span><span class="cx"> #include &quot;ApplicationCacheResource.h&quot;
</span><span class="cx"> #include &quot;Attribute.h&quot;
</span><ins>+#include &quot;Blob.h&quot;
</ins><span class="cx"> #include &quot;CSSPropertyNames.h&quot;
</span><span class="cx"> #include &quot;CSSValueKeywords.h&quot;
</span><span class="cx"> #include &quot;ChromeClient.h&quot;
</span><span class="lines">@@ -203,7 +204,6 @@
</span><span class="cx">         actionBuilder.append(#_actionType); \
</span><span class="cx">     } \
</span><span class="cx"> 
</span><del>-    ACTION(LoadMediaResource);
</del><span class="cx">     ACTION(ConfigureTextTracks);
</span><span class="cx">     ACTION(TextTrackChangesNotification);
</span><span class="cx">     ACTION(ConfigureTextTrackDisplay);
</span><span class="lines">@@ -742,18 +742,20 @@
</span><span class="cx"> void HTMLMediaElement::parseAttribute(const QualifiedName&amp; name, const AtomicString&amp; value)
</span><span class="cx"> {
</span><span class="cx">     if (name == srcAttr) {
</span><ins>+        // https://html.spec.whatwg.org/multipage/embedded-content.html#location-of-the-media-resource
+        // Location of the Media Resource
+        // 12 February 2017
+
+        // If a src attribute of a media element is set or changed, the user
+        // agent must invoke the media element's media element load algorithm.
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">         // Note, unless the restriction on requiring user action has been removed,
</span><span class="cx">         // do not begin downloading data on iOS.
</span><span class="cx">         if (!value.isNull() &amp;&amp; m_mediaSession-&gt;dataLoadingPermitted(*this))
</span><span class="cx"> #else
</span><del>-        // Trigger a reload, as long as the 'src' attribute is present.
</del><span class="cx">         if (!value.isNull())
</span><span class="cx"> #endif
</span><del>-        {
-            clearMediaPlayer(LoadMediaResource);
-            scheduleDelayedAction(LoadMediaResource);
-        }
</del><ins>+            prepareForLoad();
</ins><span class="cx">     } else if (name == controlsAttr)
</span><span class="cx">         configureMediaControls();
</span><span class="cx">     else if (name == loopAttr)
</span><span class="lines">@@ -770,7 +772,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // The attribute must be ignored if the autoplay attribute is present
</span><del>-        if (!autoplay() &amp;&amp; m_player)
</del><ins>+        if (!autoplay() &amp;&amp; !m_havePreparedToPlay &amp;&amp; m_player)
</ins><span class="cx">             m_player-&gt;setPreload(m_mediaSession-&gt;effectivePreloadForElement(*this));
</span><span class="cx"> 
</span><span class="cx">     } else if (name == mediagroupAttr)
</span><span class="lines">@@ -830,7 +832,7 @@
</span><span class="cx"> #else
</span><span class="cx">         if (m_networkState == NETWORK_EMPTY &amp;&amp; !attributeWithoutSynchronization(srcAttr).isEmpty())
</span><span class="cx"> #endif
</span><del>-            scheduleDelayedAction(LoadMediaResource);
</del><ins>+            prepareForLoad();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!m_explicitlyMuted) {
</span><span class="lines">@@ -930,11 +932,6 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::scheduleDelayedAction(%p) - setting %s flag&quot;, this, actionName(actionType).utf8().data());
</span><span class="cx"> 
</span><del>-    if ((actionType &amp; LoadMediaResource) &amp;&amp; !(m_pendingActionFlags &amp; LoadMediaResource)) {
-        prepareForLoad();
-        setFlags(m_pendingActionFlags, LoadMediaResource);
-    }
-
</del><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx">     if (actionType &amp; ConfigureTextTracks)
</span><span class="cx">         setFlags(m_pendingActionFlags, ConfigureTextTracks);
</span><span class="lines">@@ -960,9 +957,9 @@
</span><span class="cx"> void HTMLMediaElement::scheduleNextSourceChild()
</span><span class="cx"> {
</span><span class="cx">     // Schedule the timer to try the next &lt;source&gt; element WITHOUT resetting state ala prepareForLoad.
</span><del>-    LOG(Media, &quot;HTMLMediaElement::scheduleNextSourceChild(%p) - setting %s flag&quot;, this, actionName(LoadMediaResource).utf8().data());
-    setFlags(m_pendingActionFlags, LoadMediaResource);
-    m_pendingActionTimer.startOneShot(0);
</del><ins>+    m_resourceSelectionTaskQueue.enqueueTask([this] {
+        loadNextSourceChild();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::mediaPlayerActiveSourceBuffersChanged(const MediaPlayer*)
</span><span class="lines">@@ -1036,13 +1033,6 @@
</span><span class="cx">         configureTextTracks();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (pendingActions &amp; LoadMediaResource) {
-        if (m_loadState == LoadingFromSourceElement)
-            loadNextSourceChild();
-        else
-            loadInternal();
-    }
-
</del><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><span class="cx">     if (pendingActions &amp; CheckPlaybackTargetCompatablity &amp;&amp; m_isPlayingToWirelessTarget &amp;&amp; !m_player-&gt;canPlayToWirelessPlaybackTarget()) {
</span><span class="cx">         LOG(Media, &quot;HTMLMediaElement::pendingActionTimerFired(%p) - calling setShouldPlayToPlaybackTarget(false)&quot;, this);
</span><span class="lines">@@ -1071,8 +1061,7 @@
</span><span class="cx">     setAttributeWithoutSynchronization(srcAttr, url);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(MEDIA_STREAM)
-void HTMLMediaElement::setSrcObject(ScriptExecutionContext&amp; context, MediaStream* mediaStream)
</del><ins>+void HTMLMediaElement::setSrcObject(MediaProvider&amp;&amp; mediaProvider)
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: Setting the srcObject attribute may cause other changes to the media element's internal state:
</span><span class="cx">     // Specifically, if srcObject is specified, the UA must use it as the source of media, even if the src
</span><span class="lines">@@ -1081,14 +1070,14 @@
</span><span class="cx">     //
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=124896
</span><span class="cx"> 
</span><del>-    m_mediaStreamSrcObject = mediaStream;
-    if (mediaStream) {
-        m_settingMediaStreamSrcObject = true;
-        setSrc(DOMURL::createPublicURL(context, *mediaStream));
-        m_settingMediaStreamSrcObject = false;
-    }
</del><ins>+
+    // https://www.w3.org/TR/html51/semantics-embedded-content.html#dom-htmlmediaelement-srcobject
+    // 4.7.14.2. Location of the media resource
+    // srcObject: On setting, it must set the element’s assigned media provider object to the new
+    // value, and then invoke the element’s media element load algorithm.
+    m_mediaProvider = WTFMove(mediaProvider);
+    prepareForLoad();
</ins><span class="cx"> }
</span><del>-#endif
</del><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::setCrossOrigin(const AtomicString&amp; value)
</span><span class="cx"> {
</span><span class="lines">@@ -1142,7 +1131,7 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::load()
</span><span class="cx"> {
</span><del>-    Ref&lt;HTMLMediaElement&gt; protectedThis(*this); // loadInternal may result in a 'beforeload' event, which can make arbitrary DOM mutations.
</del><ins>+    Ref&lt;HTMLMediaElement&gt; protectedThis(*this); // prepareForLoad may result in a 'beforeload' event, which can make arbitrary DOM mutations.
</ins><span class="cx">     
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::load(%p)&quot;, this);
</span><span class="cx">     
</span><span class="lines">@@ -1152,19 +1141,25 @@
</span><span class="cx">         removeBehaviorsRestrictionsAfterFirstUserGesture();
</span><span class="cx"> 
</span><span class="cx">     prepareForLoad();
</span><del>-    loadInternal();
-    prepareToPlay();
</del><ins>+    m_resourceSelectionTaskQueue.enqueueTask([this] {
+        prepareToPlay();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::prepareForLoad()
</span><span class="cx"> {
</span><ins>+    // https://html.spec.whatwg.org/multipage/embedded-content.html#media-element-load-algorithm
+    // The Media Element Load Algorithm
+    // 12 February 2017
+
</ins><span class="cx">     LOG(Media, &quot;HTMLMediaElement::prepareForLoad(%p)&quot;, this);
</span><span class="cx"> 
</span><ins>+    // 1 - Abort any already-running instance of the resource selection algorithm for this element.
</ins><span class="cx">     // Perform the cleanup required for the resource load algorithm to run.
</span><span class="cx">     stopPeriodicTimers();
</span><span class="cx">     m_pendingActionTimer.stop();
</span><ins>+    m_resourceSelectionTaskQueue.cancelAllTasks();
</ins><span class="cx">     // FIXME: Figure out appropriate place to reset LoadTextTrackResource if necessary and set m_pendingActionFlags to 0 here.
</span><del>-    m_pendingActionFlags &amp;= ~LoadMediaResource;
</del><span class="cx">     m_sentEndEvent = false;
</span><span class="cx">     m_sentStalledEvent = false;
</span><span class="cx">     m_haveFiredLoadedData = false;
</span><span class="lines">@@ -1177,52 +1172,55 @@
</span><span class="cx">     m_failedToPlayToWirelessTarget = false;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    // 1 - Abort any already-running instance of the resource selection algorithm for this element.
</del><span class="cx">     m_loadState = WaitingForSource;
</span><span class="cx">     m_currentSourceNode = nullptr;
</span><span class="cx"> 
</span><del>-    // 2 - If there are any tasks from the media element's media element event task source in 
-    // one of the task queues, then remove those tasks.
</del><ins>+    createMediaPlayer();
+
+    // 2 - Let pending tasks be a list of all tasks from the media element's media element event task source in one of the task queues.
+    // 3 - For each task in pending tasks that would resolve pending play promises or reject pending play promises, immediately resolve or reject those promises in the order the corresponding tasks were queued.
+    // 4 - Remove each task in pending tasks from its task queue
</ins><span class="cx">     cancelPendingEventsAndCallbacks();
</span><span class="cx"> 
</span><del>-    // 3 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, queue
</del><ins>+    // 5 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, queue
</ins><span class="cx">     // a task to fire a simple event named abort at the media element.
</span><span class="cx">     if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE)
</span><span class="cx">         scheduleEvent(eventNames().abortEvent);
</span><span class="cx"> 
</span><del>-#if ENABLE(MEDIA_SOURCE)
-    detachMediaSource();
-#endif
-
-    createMediaPlayer();
-
-    // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps
</del><ins>+    // 6 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps
</ins><span class="cx">     if (m_networkState != NETWORK_EMPTY) {
</span><del>-        // 4.1 - Queue a task to fire a simple event named emptied at the media element.
</del><ins>+        // 6.1 - Queue a task to fire a simple event named emptied at the media element.
</ins><span class="cx">         scheduleEvent(eventNames().emptiedEvent);
</span><span class="cx"> 
</span><del>-        // 4.2 - If a fetching process is in progress for the media element, the user agent should stop it.
</del><ins>+        // 6.2 - If a fetching process is in progress for the media element, the user agent should stop it.
</ins><span class="cx">         m_networkState = NETWORK_EMPTY;
</span><span class="cx"> 
</span><del>-        // 4.3 - Forget the media element's media-resource-specific tracks.
</del><ins>+        // 6.3 - If the media element’s assigned media provider object is a MediaSource object, then detach it.
+#if ENABLE(MEDIA_SOURCE)
+        detachMediaSource();
+#endif
+
+        // 6.4 - Forget the media element's media-resource-specific tracks.
</ins><span class="cx">         forgetResourceSpecificTracks();
</span><span class="cx"> 
</span><del>-        // 4.4 - If readyState is not set to HAVE_NOTHING, then set it to that state.
</del><ins>+        // 6.5 - If readyState is not set to HAVE_NOTHING, then set it to that state.
</ins><span class="cx">         m_readyState = HAVE_NOTHING;
</span><span class="cx">         m_readyStateMaximum = HAVE_NOTHING;
</span><span class="cx"> 
</span><del>-        // 4.5 - If the paused attribute is false, then set it to true.
</del><ins>+        // 6.6 - If the paused attribute is false, then set it to true.
</ins><span class="cx">         m_paused = true;
</span><span class="cx"> 
</span><del>-        // 4.6 - If seeking is true, set it to false.
</del><ins>+        // 6.7 - If seeking is true, set it to false.
</ins><span class="cx">         clearSeeking();
</span><span class="cx"> 
</span><del>-        // 4.7 - Set the current playback position to 0.
</del><ins>+        // 6.8 - Set the current playback position to 0.
</ins><span class="cx">         //       Set the official playback position to 0.
</span><span class="cx">         //       If this changed the official playback position, then queue a task to fire a simple event named timeupdate at the media element.
</span><ins>+        m_lastSeekTime = MediaTime::zeroTime();
+        m_playedTimeRanges = TimeRanges::create();
</ins><span class="cx">         // FIXME: Add support for firing this event. e.g., scheduleEvent(eventNames().timeUpdateEvent);
</span><span class="cx"> 
</span><del>-        // 4.8 - Set the initial playback position to 0.
</del><ins>+        // 4.9 - Set the initial playback position to 0.
</ins><span class="cx">         // FIXME: Make this less subtle. The position only becomes 0 because of the createMediaPlayer() call
</span><span class="cx">         // above.
</span><span class="cx">         refreshCachedTime();
</span><span class="lines">@@ -1229,8 +1227,8 @@
</span><span class="cx"> 
</span><span class="cx">         invalidateCachedTime();
</span><span class="cx"> 
</span><del>-        // 4.9 - Set the timeline offset to Not-a-Number (NaN).
-        // 4.10 - Update the duration attribute to Not-a-Number (NaN).
</del><ins>+        // 4.10 - Set the timeline offset to Not-a-Number (NaN).
+        // 4.11 - Update the duration attribute to Not-a-Number (NaN).
</ins><span class="cx"> 
</span><span class="cx">         updateMediaController();
</span><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="lines">@@ -1238,57 +1236,42 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 5 - Set the playbackRate attribute to the value of the defaultPlaybackRate attribute.
</del><ins>+    // 7 - Set the playbackRate attribute to the value of the defaultPlaybackRate attribute.
</ins><span class="cx">     setPlaybackRate(defaultPlaybackRate());
</span><span class="cx"> 
</span><del>-    // 6 - Set the error attribute to null and the autoplaying flag to true.
</del><ins>+    // 8 - Set the error attribute to null and the autoplaying flag to true.
</ins><span class="cx">     m_error = nullptr;
</span><span class="cx">     m_autoplaying = true;
</span><span class="cx">     mediaSession().clientWillBeginAutoplaying();
</span><span class="cx"> 
</span><del>-    // 7 - Invoke the media element's resource selection algorithm.
</del><ins>+    // 9 - Invoke the media element's resource selection algorithm.
+    selectMediaResource();
</ins><span class="cx"> 
</span><del>-    // 8 - Note: Playback of any previously playing media resource for this element stops.
</del><ins>+    // 10 - Note: Playback of any previously playing media resource for this element stops.
</ins><span class="cx"> 
</span><del>-    // The resource selection algorithm
-    // 1 - Set the networkState to NETWORK_NO_SOURCE
-    m_networkState = NETWORK_NO_SOURCE;
</del><ins>+    configureMediaControls();
+}
</ins><span class="cx"> 
</span><del>-    // 2 - Asynchronously await a stable state.
</del><ins>+void HTMLMediaElement::selectMediaResource()
+{
+    // https://www.w3.org/TR/2016/REC-html51-20161101/semantics-embedded-content.html#resource-selection-algorithm
+    // The Resource Selection Algorithm
</ins><span class="cx"> 
</span><del>-    m_playedTimeRanges = TimeRanges::create();
</del><ins>+    // 1. Set the element’s networkState attribute to the NETWORK_NO_SOURCE value.
+    m_networkState = NETWORK_NO_SOURCE;
</ins><span class="cx"> 
</span><del>-    // FIXME: Investigate whether these can be moved into m_networkState != NETWORK_EMPTY block above
-    // so they are closer to the relevant spec steps.
-    m_lastSeekTime = MediaTime::zeroTime();
</del><ins>+    // 2. Set the element’s show poster flag to true.
+    setDisplayMode(Poster);
</ins><span class="cx"> 
</span><del>-    // The spec doesn't say to block the load event until we actually run the asynchronous section
-    // algorithm, but do it now because we won't start that until after the timer fires and the 
-    // event may have already fired by then.
-    MediaPlayer::Preload effectivePreload = m_mediaSession-&gt;effectivePreloadForElement(*this);
-    if (effectivePreload != MediaPlayer::None)
-        setShouldDelayLoadEvent(true);
</del><ins>+    // 3. Set the media element’s delaying-the-load-event flag to true (this delays the load event).
+    setShouldDelayLoadEvent(true);
</ins><span class="cx"> 
</span><del>-#if PLATFORM(IOS)
-    if (effectivePreload != MediaPlayer::None &amp;&amp; m_mediaSession-&gt;allowsAutomaticMediaDataLoading(*this))
-        prepareToPlay();
-#endif
</del><ins>+    // 4. in parallel await a stable state, allowing the task that invoked this algorithm to continue.
+    if (m_resourceSelectionTaskQueue.hasPendingTasks())
+        return;
</ins><span class="cx"> 
</span><del>-    configureMediaControls();
-}
-
-void HTMLMediaElement::loadInternal()
-{
-    LOG(Media, &quot;HTMLMediaElement::loadInternal(%p)&quot;, this);
-
-    // Some of the code paths below this function dispatch the BeforeLoad event. This ASSERT helps
-    // us catch those bugs more quickly without needing all the branches to align to actually
-    // trigger the event.
-    ASSERT(NoEventDispatchAssertion::isEventAllowedInMainThread());
-
-    // If we can't start a load right away, start it later.
</del><span class="cx">     if (!m_mediaSession-&gt;pageAllowsDataLoading(*this)) {
</span><del>-        LOG(Media, &quot;HTMLMediaElement::loadInternal(%p) - not allowed to load in background, waiting&quot;, this);
</del><ins>+        LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) - not allowed to load in background, waiting&quot;, this);
</ins><span class="cx">         setShouldDelayLoadEvent(false);
</span><span class="cx">         if (m_isWaitingUntilMediaCanStart)
</span><span class="cx">             return;
</span><span class="lines">@@ -1297,56 +1280,50 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    clearFlags(m_pendingActionFlags, LoadMediaResource);
-
-    // Once the page has allowed an element to load media, it is free to load at will. This allows a 
-    // playlist that starts in a foreground tab to continue automatically if the tab is subsequently 
</del><ins>+    // Once the page has allowed an element to load media, it is free to load at will. This allows a
+    // playlist that starts in a foreground tab to continue automatically if the tab is subsequently
</ins><span class="cx">     // put into the background.
</span><span class="cx">     m_mediaSession-&gt;removeBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
</span><span class="cx"> 
</span><ins>+
+    m_resourceSelectionTaskQueue.enqueueTask([this]  {
+        // 5. If the media element’s blocked-on-parser flag is false, then populate the list of pending text tracks.
</ins><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><del>-    if (hasMediaControls())
-        mediaControls()-&gt;changedClosedCaptionsVisibility();
</del><ins>+        if (hasMediaControls())
+            mediaControls()-&gt;changedClosedCaptionsVisibility();
</ins><span class="cx"> 
</span><del>-    // HTMLMediaElement::textTracksAreReady will need &quot;... the text tracks whose mode was not in the
-    // disabled state when the element's resource selection algorithm last started&quot;.
-    m_textTracksWhenResourceSelectionBegan.clear();
-    if (m_textTracks) {
-        for (unsigned i = 0; i &lt; m_textTracks-&gt;length(); ++i) {
-            TextTrack* track = m_textTracks-&gt;item(i);
-            if (track-&gt;mode() != TextTrack::Mode::Disabled)
-                m_textTracksWhenResourceSelectionBegan.append(track);
</del><ins>+        // HTMLMediaElement::textTracksAreReady will need &quot;... the text tracks whose mode was not in the
+        // disabled state when the element's resource selection algorithm last started&quot;.
+        // FIXME: Update this to match &quot;populate the list of pending text tracks&quot; step.
+        m_textTracksWhenResourceSelectionBegan.clear();
+        if (m_textTracks) {
+            for (unsigned i = 0; i &lt; m_textTracks-&gt;length(); ++i) {
+                TextTrack* track = m_textTracks-&gt;item(i);
+                if (track-&gt;mode() != TextTrack::Mode::Disabled)
+                    m_textTracksWhenResourceSelectionBegan.append(track);
+            }
</ins><span class="cx">         }
</span><del>-    }
</del><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    selectMediaResource();
-}
</del><ins>+        enum Mode { None, Object, Attribute, Children };
+        Mode mode = None;
</ins><span class="cx"> 
</span><del>-void HTMLMediaElement::selectMediaResource()
-{
-    LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p)&quot;, this);
-
-    ASSERT(m_player);
-    if (!m_player)
-        return;
-
-    enum Mode { attribute, children };
-
-    // 3 - If the media element has a src attribute, then let mode be attribute.
-    Mode mode = attribute;
-    if (!hasAttributeWithoutSynchronization(srcAttr)) {
-        // Otherwise, if the media element does not have a src attribute but has a source 
-        // element child, then let mode be children and let candidate be the first such 
-        // source element child in tree order.
-        if (auto firstSource = childrenOfType&lt;HTMLSourceElement&gt;(*this).first()) {
-            mode = children;
</del><ins>+        if (m_mediaProvider) {
+            // 6. If the media element has an assigned media provider object, then let mode be object.
+            mode = Object;
+        } else if (hasAttributeWithoutSynchronization(srcAttr)) {
+            //    Otherwise, if the media element has no assigned media provider object but has a src attribute, then let mode be attribute.
+            mode = Attribute;
+        } else if (auto firstSource = childrenOfType&lt;HTMLSourceElement&gt;(*this).first()) {
+            //    Otherwise, if the media element does not have an assigned media provider object and does not have a src attribute,
+            //    but does have a source element child, then let mode be children and let candidate be the first such source element
+            //    child in tree order.
+            mode = Children;
</ins><span class="cx">             m_nextChildNodeToConsider = firstSource;
</span><span class="cx">             m_currentSourceNode = nullptr;
</span><span class="cx">         } else {
</span><del>-            // Otherwise the media element has neither a src attribute nor a source element 
-            // child: set the networkState to NETWORK_EMPTY, and abort these steps; the 
-            // synchronous section ends.
</del><ins>+            //  Otherwise the media element has no assigned media provider object and has neither a src attribute nor a source
+            //  element child: set the networkState to NETWORK_EMPTY, and abort these steps; the synchronous section ends.
</ins><span class="cx">             m_loadState = WaitingForSource;
</span><span class="cx">             setShouldDelayLoadEvent(false);
</span><span class="cx">             m_networkState = NETWORK_EMPTY;
</span><span class="lines">@@ -1354,49 +1331,95 @@
</span><span class="cx">             LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) - nothing to load&quot;, this);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-    }
</del><span class="cx"> 
</span><del>-    // 4 - Set the media element's delaying-the-load-event flag to true (this delays the load event), 
-    // and set its networkState to NETWORK_LOADING.
-    setShouldDelayLoadEvent(true);
-    m_networkState = NETWORK_LOADING;
</del><ins>+        // 7. Set the media element’s networkState to NETWORK_LOADING.
+        m_networkState = NETWORK_LOADING;
</ins><span class="cx"> 
</span><del>-    // 5 - Queue a task to fire a simple event named loadstart at the media element.
-    scheduleEvent(eventNames().loadstartEvent);
</del><ins>+        // 8. Queue a task to fire a simple event named loadstart at the media element.
+        scheduleEvent(eventNames().loadstartEvent);
</ins><span class="cx"> 
</span><del>-    // 6 - If mode is attribute, then run these substeps
-    if (mode == attribute) {
-        m_loadState = LoadingFromSrcAttr;
</del><ins>+        // 9. Run the appropriate steps from the following list:
+        // ↳ If mode is object
+        if (mode == Object) {
+            // 1. Set the currentSrc attribute to the empty string.
+            m_currentSrc = URL();
</ins><span class="cx"> 
</span><del>-        // If the src attribute's value is the empty string ... jump down to the failed step below
-        URL mediaURL = getNonEmptyURLAttribute(srcAttr);
-        if (mediaURL.isEmpty()) {
-            mediaLoadingFailed(MediaPlayer::FormatError);
-            LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) -  empty 'src'&quot;, this);
</del><ins>+            // 2. End the synchronous section, continuing the remaining steps in parallel.
+            // 3. Run the resource fetch algorithm with the assigned media provider object.
+            WTF::visit(WTF::makeVisitor(
+#if ENABLE(MEDIA_STREAM)
+                [this](RefPtr&lt;MediaStream&gt; stream) { m_mediaStreamSrcObject = stream; },
+#endif
+#if ENABLE(MEDIA_SOURCE)
+                [this](RefPtr&lt;MediaSource&gt; source) { m_mediaSource = source; },
+#endif
+                [this](RefPtr&lt;Blob&gt; blob) { m_blob = blob; }
+            ), m_mediaProvider.value());
+
+            ContentType contentType;
+            loadResource(URL(), contentType, String());
+            LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) - using 'srcObject' property&quot;, this);
+
+            //    If that algorithm returns without aborting this one, then the load failed.
+            // 4. Failed with media provider: Reaching this step indicates that the media resource
+            //    failed to load. Queue a task to run the dedicated media source failure steps.
+            // 5. Wait for the task queued by the previous step to have executed.
+            // 6. Abort these steps. The element won’t attempt to load another resource until this
+            //    algorithm is triggered again.
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!isSafeToLoadURL(mediaURL, Complain) || !dispatchBeforeLoadEvent(mediaURL.string())) {
-            mediaLoadingFailed(MediaPlayer::FormatError);
</del><ins>+        // ↳ If mode is attribute
+        if (mode == Attribute) {
+            m_loadState = LoadingFromSrcAttr;
+
+            // 1. If the src attribute’s value is the empty string, then end the synchronous section,
+            //    and jump down to the failed with attribute step below.
+            // 2. Let absolute URL be the absolute URL that would have resulted from parsing the URL
+            //    specified by the src attribute’s value relative to the media element when the src
+            //    attribute was last changed.
+            URL absoluteURL = getNonEmptyURLAttribute(srcAttr);
+            if (absoluteURL.isEmpty()) {
+                mediaLoadingFailed(MediaPlayer::FormatError);
+                LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) -  empty 'src'&quot;, this);
+                return;
+            }
+
+            if (!isSafeToLoadURL(absoluteURL, Complain) || !dispatchBeforeLoadEvent(absoluteURL.string())) {
+                mediaLoadingFailed(MediaPlayer::FormatError);
+                return;
+            }
+
+            // 3. If absolute URL was obtained successfully, set the currentSrc attribute to absolute URL.
+            m_currentSrc = absoluteURL;
+
+            // 4. End the synchronous section, continuing the remaining steps in parallel.
+            // 5. If absolute URL was obtained successfully, run the resource fetch algorithm with absolute
+            //    URL. If that algorithm returns without aborting this one, then the load failed.
+
+            // No type or key system information is available when the url comes
+            // from the 'src' attribute so MediaPlayer
+            // will have to pick a media engine based on the file extension.
+            ContentType contentType;
+            loadResource(absoluteURL, contentType, String());
+            LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) - using 'src' attribute url&quot;, this);
+
+            // 6. Failed with attribute: Reaching this step indicates that the media resource failed to load
+            //    or that the given URL could not be resolved. Queue a task to run the dedicated media source failure steps.
+            // 7. Wait for the task queued by the previous step to have executed.
+            // 8. Abort these steps. The element won’t attempt to load another resource until this algorithm is triggered again.
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // No type or key system information is available when the url comes
-        // from the 'src' attribute so MediaPlayer
-        // will have to pick a media engine based on the file extension.
-        ContentType contentType((String()));
-        loadResource(mediaURL, contentType, String());
-        LOG(Media, &quot;HTMLMediaElement::selectMediaResource(%p) - using 'src' attribute url&quot;, this);
-        return;
-    }
-
-    // Otherwise, the source elements will be used
-    loadNextSourceChild();
</del><ins>+        // ↳ Otherwise (mode is children)
+        // (Ctd. in loadNextSourceChild())
+        loadNextSourceChild();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::loadNextSourceChild()
</span><span class="cx"> {
</span><del>-    ContentType contentType((String()));
</del><ins>+    ContentType contentType;
</ins><span class="cx">     String keySystem;
</span><span class="cx">     URL mediaURL = selectNextSourceChild(&amp;contentType, &amp;keySystem, Complain);
</span><span class="cx">     if (!mediaURL.isValid()) {
</span><span class="lines">@@ -1413,7 +1436,7 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLMediaElement::loadResource(const URL&amp; initialURL, ContentType&amp; contentType, const String&amp; keySystem)
</span><span class="cx"> {
</span><del>-    ASSERT(isSafeToLoadURL(initialURL, Complain));
</del><ins>+    ASSERT(initialURL.isEmpty() || isSafeToLoadURL(initialURL, Complain));
</ins><span class="cx"> 
</span><span class="cx">     LOG(Media, &quot;HTMLMediaElement::loadResource(%p) - %s, %s, %s&quot;, this, urlForLoggingMedia(initialURL).utf8().data(), contentType.raw().utf8().data(), keySystem.utf8().data());
</span><span class="cx"> 
</span><span class="lines">@@ -1430,7 +1453,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     URL url = initialURL;
</span><del>-    if (!frame-&gt;loader().willLoadMediaElementURL(url)) {
</del><ins>+    if (!url.isEmpty() &amp;&amp; !frame-&gt;loader().willLoadMediaElementURL(url)) {
</ins><span class="cx">         mediaLoadingFailed(MediaPlayer::FormatError);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -1449,7 +1472,7 @@
</span><span class="cx"> 
</span><span class="cx">     // If the URL should be loaded from the application cache, pass the URL of the cached file to the media engine.
</span><span class="cx">     ApplicationCacheResource* resource = nullptr;
</span><del>-    if (frame-&gt;loader().documentLoader()-&gt;applicationCacheHost().shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource)) {
</del><ins>+    if (!url.isEmpty() &amp;&amp; frame-&gt;loader().documentLoader()-&gt;applicationCacheHost().shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource)) {
</ins><span class="cx">         // Resources that are not present in the manifest will always fail to load (at least, after the
</span><span class="cx">         // cache has been primed the first time), making the testing of offline applications simpler.
</span><span class="cx">         if (!resource || resource-&gt;path().isEmpty()) {
</span><span class="lines">@@ -1483,7 +1506,7 @@
</span><span class="cx">     // Reset display mode to force a recalculation of what to show because we are resetting the player.
</span><span class="cx">     setDisplayMode(Unknown);
</span><span class="cx"> 
</span><del>-    if (!autoplay())
</del><ins>+    if (!autoplay() &amp;&amp; !m_havePreparedToPlay)
</ins><span class="cx">         m_player-&gt;setPreload(m_mediaSession-&gt;effectivePreloadForElement(*this));
</span><span class="cx">     m_player-&gt;setPreservesPitch(m_webkitPreservesPitch);
</span><span class="cx"> 
</span><span class="lines">@@ -1497,21 +1520,17 @@
</span><span class="cx"> 
</span><span class="cx">     bool loadAttempted = false;
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><del>-    ASSERT(!m_mediaSource);
-
-    if (url.protocolIs(mediaSourceBlobProtocol))
</del><ins>+    if (!m_mediaSource &amp;&amp; url.protocolIs(mediaSourceBlobProtocol))
</ins><span class="cx">         m_mediaSource = MediaSource::lookup(url.string());
</span><span class="cx"> 
</span><span class="cx">     if (m_mediaSource) {
</span><del>-        if (m_mediaSource-&gt;attachToElement(*this))
-            m_player-&gt;load(url, contentType, m_mediaSource.get());
-        else {
</del><ins>+        loadAttempted = true;
+        if (!m_mediaSource-&gt;attachToElement(*this) || !m_player-&gt;load(url, contentType, m_mediaSource.get())) {
</ins><span class="cx">             // Forget our reference to the MediaSource, so we leave it alone
</span><span class="cx">             // while processing remainder of load failure.
</span><span class="cx">             m_mediaSource = nullptr;
</span><span class="cx">             mediaLoadingFailed(MediaPlayer::FormatError);
</span><span class="cx">         }
</span><del>-        loadAttempted = true;
</del><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -1528,6 +1547,12 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    if (!loadAttempted &amp;&amp; m_blob) {
+        loadAttempted = true;
+        if (!m_player-&gt;load(m_blob-&gt;url(), contentType, keySystem))
+            mediaLoadingFailed(MediaPlayer::FormatError);
+    }
+
</ins><span class="cx">     if (!loadAttempted &amp;&amp; !m_player-&gt;load(url, contentType, keySystem))
</span><span class="cx">         mediaLoadingFailed(MediaPlayer::FormatError);
</span><span class="cx"> 
</span><span class="lines">@@ -3121,7 +3146,7 @@
</span><span class="cx"> 
</span><span class="cx">     // 4.8.10.9. Playing the media resource
</span><span class="cx">     if (!m_player || m_networkState == NETWORK_EMPTY)
</span><del>-        scheduleDelayedAction(LoadMediaResource);
</del><ins>+        prepareForLoad();
</ins><span class="cx"> 
</span><span class="cx">     if (endedPlayback())
</span><span class="cx">         seekInternal(MediaTime::zeroTime());
</span><span class="lines">@@ -3209,7 +3234,7 @@
</span><span class="cx">         // don't trigger loading if a script calls pause().
</span><span class="cx">         if (!m_mediaSession-&gt;playbackPermitted(*this))
</span><span class="cx">             return;
</span><del>-        scheduleDelayedAction(LoadMediaResource);
</del><ins>+        prepareForLoad();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_autoplaying = false;
</span><span class="lines">@@ -4255,8 +4280,8 @@
</span><span class="cx">     // attribute and whose networkState has the value NETWORK_EMPTY, the user agent must invoke 
</span><span class="cx">     // the media element's resource selection algorithm.
</span><span class="cx">     if (networkState() == HTMLMediaElement::NETWORK_EMPTY) {
</span><del>-        scheduleDelayedAction(LoadMediaResource);
</del><span class="cx">         m_nextChildNodeToConsider = source;
</span><ins>+        selectMediaResource();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -5041,6 +5066,8 @@
</span><span class="cx">     detachMediaSource();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    m_blob = nullptr;
+
</ins><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx">     forgetResourceSpecificTracks();
</span><span class="cx"> #endif
</span><span class="lines">@@ -5203,7 +5230,7 @@
</span><span class="cx">         //  MEDIA_ERR_ABORTED while the abortEvent is being sent, but cleared immediately afterwards).
</span><span class="cx">         // This behavior is not specified but it seems like a sensible thing to do.
</span><span class="cx">         // As it is not safe to immedately start loading now, let's schedule a load.
</span><del>-        scheduleDelayedAction(LoadMediaResource);
</del><ins>+        prepareForLoad();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     updateRenderer();
</span><span class="lines">@@ -5728,7 +5755,7 @@
</span><span class="cx">     ASSERT(m_isWaitingUntilMediaCanStart || m_pausedInternal);
</span><span class="cx">     if (m_isWaitingUntilMediaCanStart) {
</span><span class="cx">         m_isWaitingUntilMediaCanStart = false;
</span><del>-        loadInternal();
</del><ins>+        selectMediaResource();
</ins><span class="cx">     }
</span><span class="cx">     if (m_pausedInternal)
</span><span class="cx">         setPausedInternal(false);
</span><span class="lines">@@ -6002,8 +6029,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE)
</span><del>-    if (m_mediaSource)
-        m_mediaSource-&gt;detachFromElement(*this);
</del><ins>+    detachMediaSource();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.h        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> class AudioSourceProvider;
</span><span class="cx"> class AudioTrackList;
</span><span class="cx"> class AudioTrackPrivate;
</span><ins>+class Blob;
</ins><span class="cx"> class DOMError;
</span><span class="cx"> class DeferredPromise;
</span><span class="cx"> class DisplaySleepDisabler;
</span><span class="lines">@@ -92,6 +93,15 @@
</span><span class="cx"> using CueList = Vector&lt;CueInterval&gt;;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+using MediaProvider = std::optional&lt;Variant&lt;
+#if ENABLE(MEDIA_STREAM)
+    RefPtr&lt;MediaStream&gt;,
+#endif
+#if ENABLE(MEDIA_SOURCE)
+    RefPtr&lt;MediaSource&gt;,
+#endif
+    RefPtr&lt;Blob&gt;&gt;&gt;;
+
</ins><span class="cx"> class HTMLMediaElement
</span><span class="cx">     : public HTMLElement
</span><span class="cx">     , public ActiveDOMObject
</span><span class="lines">@@ -164,10 +174,8 @@
</span><span class="cx">     void setSrc(const String&amp;);
</span><span class="cx">     const URL&amp; currentSrc() const { return m_currentSrc; }
</span><span class="cx"> 
</span><del>-#if ENABLE(MEDIA_STREAM)
-    MediaStream* srcObject() const { return m_mediaStreamSrcObject.get(); }
-    void setSrcObject(ScriptExecutionContext&amp;, MediaStream*);
-#endif
</del><ins>+    const MediaProvider&amp; srcObject() const { return m_mediaProvider; }
+    void setSrcObject(MediaProvider&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT void setCrossOrigin(const AtomicString&amp;);
</span><span class="cx">     WEBCORE_EXPORT String crossOrigin() const;
</span><span class="lines">@@ -698,7 +706,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     // These &quot;internal&quot; functions do not check user gesture restrictions.
</span><del>-    void loadInternal();
</del><span class="cx">     bool playInternal();
</span><span class="cx">     void pauseInternal();
</span><span class="cx"> 
</span><span class="lines">@@ -828,6 +835,7 @@
</span><span class="cx">     GenericTaskQueue&lt;Timer&gt; m_pauseAfterDetachedTaskQueue;
</span><span class="cx">     GenericTaskQueue&lt;Timer&gt; m_updatePlaybackControlsManagerQueue;
</span><span class="cx">     GenericTaskQueue&lt;Timer&gt; m_playbackControlsManagerBehaviorRestrictionsQueue;
</span><ins>+    GenericTaskQueue&lt;Timer&gt; m_resourceSelectionTaskQueue;
</ins><span class="cx">     RefPtr&lt;TimeRanges&gt; m_playedTimeRanges;
</span><span class="cx">     GenericEventQueue m_asyncEventQueue;
</span><span class="cx"> 
</span><span class="lines">@@ -1012,6 +1020,9 @@
</span><span class="cx"> 
</span><span class="cx">     friend class TrackDisplayUpdateScope;
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;Blob&gt; m_blob;
+    MediaProvider m_mediaProvider;
+
</ins><span class="cx"> #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
</span><span class="cx">     RefPtr&lt;WebKitMediaKeys&gt; m_webKitMediaKeys;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.idl (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.idl        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/html/HTMLMediaElement.idl        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -23,6 +23,16 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+
+typedef (
+#if defined(ENABLE_MEDIA_STREAM) &amp;&amp; ENABLE_MEDIA_STREAM
+    MediaStream or
+#endif
+#if defined(ENABLE_MEDIA_SOURCE) &amp;&amp; ENABLE_MEDIA_SOURCE
+    MediaSource or
+#endif
+    Blob) MediaProvider;
+
</ins><span class="cx"> [
</span><span class="cx">     ActiveDOMObject,
</span><span class="cx">     Conditional=VIDEO,
</span><span class="lines">@@ -35,6 +45,7 @@
</span><span class="cx"> 
</span><span class="cx">     // network state
</span><span class="cx">     [Reflect, URL] attribute USVString src;
</span><ins>+    attribute MediaProvider? srcObject;
</ins><span class="cx">     [URL] readonly attribute USVString currentSrc;
</span><span class="cx">     attribute DOMString? crossOrigin;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformContentTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ContentType.h (212310 => 212311)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ContentType.h        2017-02-14 19:13:04 UTC (rev 212310)
+++ trunk/Source/WebCore/platform/ContentType.h        2017-02-14 19:17:14 UTC (rev 212311)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx">     class ContentType {
</span><span class="cx">     public:
</span><span class="cx">         explicit ContentType(const String&amp; type);
</span><ins>+        ContentType() = default;
</ins><span class="cx"> 
</span><span class="cx">         String parameter(const String&amp; parameterName) const;
</span><span class="cx">         String type() const;
</span></span></pre>
</div>
</div>

</body>
</html>