<!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>[173401] trunk/Source/WebCore</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/173401">173401</a></dd>
<dt>Author</dt> <dd>dino@apple.com</dd>
<dt>Date</dt> <dd>2014-09-08 15:33:21 -0700 (Mon, 08 Sep 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Separate the Apple media controls module from other ports
https://bugs.webkit.org/show_bug.cgi?id=136644
rdar://problem/18270969

Reviewed by Eric Carlson.

Make a mediaControlsBase.{js|css} that acts as the base
class for the EFL and GTK ports (they were using mediaControlsApple).
Over time, the Apple-specific controls may use more of the
Base class.

* Modules/mediacontrols/mediaControlsBase.css: Added.
* Modules/mediacontrols/mediaControlsBase.js: Added.
* PlatformEfl.cmake:
* PlatformGTK.cmake:
* platform/efl/RenderThemeEfl.cpp:
(WebCore::RenderThemeEfl::mediaControlsStyleSheet): Load Base rather than Apple.
(WebCore::RenderThemeEfl::mediaControlsScript): Ditto.
* rendering/RenderThemeGtk.cpp:
(WebCore::RenderThemeGtk::mediaControlsScript): Ditto.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorePlatformEflcmake">trunk/Source/WebCore/PlatformEfl.cmake</a></li>
<li><a href="#trunkSourceWebCorePlatformGTKcmake">trunk/Source/WebCore/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebCoreplatformeflRenderThemeEflcpp">trunk/Source/WebCore/platform/efl/RenderThemeEfl.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderThemeGtkcpp">trunk/Source/WebCore/rendering/RenderThemeGtk.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreModulesmediacontrolsmediaControlsBasecss">trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css</a></li>
<li><a href="#trunkSourceWebCoreModulesmediacontrolsmediaControlsBasejs">trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173400 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-09-08 21:40:08 UTC (rev 173400)
+++ trunk/Source/WebCore/ChangeLog        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2014-09-08  Dean Jackson  &lt;dino@apple.com&gt;
+
+        Separate the Apple media controls module from other ports
+        https://bugs.webkit.org/show_bug.cgi?id=136644
+        rdar://problem/18270969
+
+        Reviewed by Eric Carlson.
+
+        Make a mediaControlsBase.{js|css} that acts as the base
+        class for the EFL and GTK ports (they were using mediaControlsApple).
+        Over time, the Apple-specific controls may use more of the
+        Base class.
+
+        * Modules/mediacontrols/mediaControlsBase.css: Added.
+        * Modules/mediacontrols/mediaControlsBase.js: Added.
+        * PlatformEfl.cmake:
+        * PlatformGTK.cmake:
+        * platform/efl/RenderThemeEfl.cpp:
+        (WebCore::RenderThemeEfl::mediaControlsStyleSheet): Load Base rather than Apple.
+        (WebCore::RenderThemeEfl::mediaControlsScript): Ditto.
+        * rendering/RenderThemeGtk.cpp:
+        (WebCore::RenderThemeGtk::mediaControlsScript): Ditto.
+
</ins><span class="cx"> 2014-09-08  Jochen Eisinger  &lt;jochen@chromium.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Always update the referrer header in CachedResource
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediacontrolsmediaControlsBasecss"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css (0 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -0,0 +1,758 @@
</span><ins>+/*
+ * Copyright (C) 2013, 2014 Apple Inc.  All rights reserved.
+ *
+ * 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 APPLE INC. ``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 APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * 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. 
+ */
+
+audio {
+    width: 200px;
+    height: 25px;
+}
+
+body:-webkit-full-page-media {
+    background-color: rgb(38, 38, 38);
+}
+
+video:-webkit-full-page-media {
+    margin: auto;
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+    bottom: 0px;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel.no-video {
+    opacity: 1;
+}
+
+::-webkit-media-controls {
+    width: inherit;
+    height: inherit;
+    position: relative;
+    display: -webkit-flex;
+    -webkit-align-items: stretch;
+    -webkit-justify-content: flex-end;
+    -webkit-flex-direction: column;
+}
+
+video::-webkit-media-text-track-container,
+audio::-webkit-media-text-track-container {
+    position: relative;
+    -webkit-flex: 1 1 auto;
+}
+
+video::-webkit-media-controls-panel-composited-parent {
+    -webkit-transform: translateZ(0);
+    width: 100%;
+}
+
+video::-webkit-media-controls-panel,
+audio::-webkit-media-controls-panel {
+    box-sizing: border-box;
+    position: relative;
+    bottom: 0;
+    width: 100%;
+    padding-top: 1px;
+    min-height: 25px;
+    height: 25px;
+    line-height: 25px;
+    -webkit-user-select: none;
+    background-color: transparent;
+    background-image: -webkit-linear-gradient(top,
+        rgba(0,  0,  0,  .92) 0,
+        rgba(0,  0,  0,  .92) 1px,
+        rgba(89, 89, 89, .92) 1px,
+        rgba(89, 89, 89, .92) 2px,
+        rgba(60, 60, 60, .92) 2px,
+        rgba(35, 35, 35, .92) 12px,
+        rgba(30, 30, 30, .92) 12px,
+        rgba(30, 30, 30, .92) 13px,
+        rgba(25, 25, 25, .92) 13px,
+        rgba(17, 17, 17, .92) 100%
+    );
+
+    display: -webkit-flex;
+    -webkit-flex-direction: row;
+    -webkit-align-items: center;
+    -webkit-user-select: none;
+
+    direction: ltr;
+
+    transition: opacity 0.25s linear;
+}
+
+video::-webkit-media-controls-panel {
+    cursor: none;
+    opacity: 0;
+}
+
+video::-webkit-media-controls-panel.show,
+video::-webkit-media-controls-panel.paused,
+video::-webkit-media-controls-panel:hover {
+    cursor: inherit;
+    opacity: 1;
+}
+
+video::-webkit-media-controls-panel button,
+audio::-webkit-media-controls-panel button {
+    -webkit-appearance: none;
+    display: block;
+    padding: 0;
+    border: 0;
+    height: 16px;
+    width: 16px;
+    background-color: transparent;
+    color: white;
+    background-origin: content-box;
+    background-repeat: no-repeat;
+    background-position: center;
+    -webkit-filter: drop-shadow(black 0 1px 1px);
+}
+
+video::-webkit-media-controls-panel button:active,
+audio::-webkit-media-controls-panel button:active {
+    -webkit-filter: drop-shadow(white 0 0 10px);
+}
+
+video::-webkit-media-controls-rewind-button,
+audio::-webkit-media-controls-rewind-button {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 17&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.44444&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.44444&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.55555&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.55555&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;m 7.9131,2 0,-1.548 -2.586,2.155 0,-2.171 -2.582,2.208 2.582,2.175 0,-2.139 2.586,2.155 0,-1.276 c 3.138,0.129 5.491,2.681 5.543,5.838 l -1.031,0 0.016,0.215 1.015,0 c -0.06,3.19 -2.629,5.765 -5.819,5.833 l 0,-1.018 -0.214,0 0,1.021 c -3.21,-0.047 -5.801,-2.631 -5.862,-5.836 l 1.045,0 -0.016,-0.215 -1.045,0 c -0.052,-0.288 -0.318,-0.654 -0.766,-0.654 -0.538,0 -0.755,0.484 -0.755,0.75 0,4.146 3.331,7.506 7.476,7.506 4.146,0 7.506,-3.36 7.506,-7.506 0,-4.059 -3.066,-7.357 -7.093,-7.493&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;path d=&quot;m 5.1729,11.0518 c -0.38,0 -0.668,-0.129 -0.945,-0.366 -0.083,-0.071 -0.186,-0.134 -0.338,-0.134 -0.277,0 -0.511,0.238 -0.511,0.521 0,0.154 0.083,0.301 0.179,0.383 0.394,0.346 0.911,0.563 1.601,0.563 1.077,0 1.739,-0.681 1.739,-1.608 l 0,-0.013 c 0,-0.911 -0.641,-1.265 -1.296,-1.376 l 0.945,-0.919 c 0.193,-0.19 0.317,-0.337 0.317,-0.604 0,-0.294 -0.228,-0.477 -0.538,-0.477 l -2.354,0 c -0.248,0 -0.455,0.21 -0.455,0.464 0,0.253 0.207,0.463 0.455,0.463 l 1.485,0 -0.939,0.961 c -0.166,0.169 -0.228,0.295 -0.228,0.444 0,0.25 0.207,0.463 0.455,0.463 l 0.166,0 c 0.594,0 0.945,0.222 0.945,0.624 l 0,0.012 c 0,0.367 -0.282,0.599 -0.683,0.599&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;path d=&quot;m 10.354,9.5342 c 0,0.876 -0.379,1.525 -0.979,1.525 -0.599,0 -0.992,-0.655 -0.992,-1.539 l 0,-0.012 c 0,-0.884 0.388,-1.527 0.979,-1.527 0.592,0 0.992,0.663 0.992,1.539 l 0,0.014 z m -0.979,-2.512 c -1.197,0 -2.008,1.097 -2.008,2.498 l 0,0.014 c 0,1.401 0.792,2.484 1.995,2.484 1.205,0 2.01,-1.097 2.01,-2.498 l 0,-0.012 c 0,-1.402 -0.805,-2.486 -1.997,-2.486&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+    width: 16px;
+    height: 18px;
+    margin-bottom: 1px;
+    margin-left: 6px;
+    margin-right: 4px;
+}
+
+video::-webkit-media-controls-play-button,
+audio::-webkit-media-controls-play-button {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 15&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 0,0 v 16 h 6 v -16 h -6 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;path d=&quot;M 9,0 v 16 h 6 v -16 h -6 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+    margin-left: 6px;
+    margin-right: 1px;
+}
+
+video::-webkit-media-controls-play-button.paused,
+audio::-webkit-media-controls-play-button.paused {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 15&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 0,0 15,7 0,15 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+}
+
+video::-webkit-media-controls-panel .mute-box,
+audio::-webkit-media-controls-panel .mute-box {
+    width: 22px;
+    height: 22px;
+    margin-right: 2px;
+
+    position: relative;
+    display: -webkit-flex;
+    -webkit-flex-direction: column;
+    -webkit-justify-content: center;
+    -webkit-align-items: center;
+}
+
+video::-webkit-media-controls-mute-button,
+audio::-webkit-media-controls-mute-button,
+video::-webkit-media-controls-volume-max-button {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 15&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;m 0,9 0,-4 3,0 3,-3 0,10 -3,-3 -3,0 z&quot; style=&quot;fill:url(#gradient) &quot;/&gt;&lt;path d=&quot;m 10.449,1.087 c 1.963,1.055 3.322,3.291 3.322,5.881 0,2.642 -1.402,4.913 -3.424,5.945&quot; style=&quot;fill:none;stroke:url(#gradient);stroke-width:1.25;stroke-linecap:round;&quot;/&gt;&lt;path d=&quot;m 9.13,3.134 c 1.289,0.681 2.181,2.142 2.181,3.835 0,1.743001 -0.939,3.24 -2.285,3.897&quot; style=&quot;fill:none;stroke:url(#gradient);stroke-width:1.25;stroke-linecap:round;&quot;/&gt;&lt;path d=&quot;M 7.794,5.175 C 8.403001,5.491 8.827001,6.167 8.827001,6.971 8.827001,7.818 8.356,8.537001 7.688,8.826&quot; style=&quot;fill:none;stroke:url(#gradient);stroke-width:1.25;stroke-linecap:round;&quot;/&gt;&lt;/svg&gt;');
+    width: 14px;
+}
+
+video::-webkit-media-controls-panel .volume-box,
+audio::-webkit-media-controls-panel .volume-box {
+    position: absolute;
+    box-sizing: border-box;
+    height: 22px;
+    bottom: 0;
+    left: 0;
+
+    -webkit-transform: rotate(-90deg);
+    -webkit-transform-origin: 11px 11px;
+
+    background-color: transparent;
+    background-image: -webkit-linear-gradient(
+        left,
+        rgba(17, 17, 17,  0.92),
+        rgba(42, 42, 42, 0.92)
+    );
+    border: 1px solid rgba(0, 0, 0, 0.95);
+    border-radius: 12px;
+
+    display: -webkit-flex;
+    -webkit-flex-direction: row;
+    -webkit-align-items: center;
+    -webkit-justify-content: flex-end;
+
+    opacity: 0;
+    /* make zero width (rather than display:none) for AX and FKA */
+    width: 0; /* will become 114px when shown */
+
+}
+
+/* FIXME: needs CSS4 !subject selector to show when slider inside .volume-box is focused */
+video::-webkit-media-controls-panel .mute-box:hover .volume-box,
+video::-webkit-media-controls-panel .volume-box:hover,
+video::-webkit-media-controls-panel .volume-box:active,
+audio::-webkit-media-controls-panel .mute-box:hover .volume-box,
+audio::-webkit-media-controls-panel .volume-box:hover,
+audio::-webkit-media-controls-panel .volume-box:active {
+    opacity: 1;
+    /* resize to usable amount (rather than display:none) for AX and FKA */
+    width: 114px;
+}
+
+audio::-webkit-media-controls-volume-slider,
+video::-webkit-media-controls-volume-slider {
+    -webkit-appearance: none;
+    box-sizing: border-box;
+    height: 10px;
+    width: 80px;
+    padding: 0;
+    margin-right: 6px;
+
+    border-radius: 5px;
+    background-color: transparent;
+    background-image: -webkit-linear-gradient(
+        top,
+        rgba(15, 15, 15, .85) 0,
+        rgba(23, 23, 23, .85) 50%,
+        rgba(15, 15, 15, .85) 100%
+    );
+    border: 1px solid rgba(0, 0, 0, 0.875);
+}
+
+video::-webkit-media-controls-volume-slider::-webkit-slider-thumb,
+audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb {
+    -webkit-appearance: none;
+    width: 8px;
+    height: 8px;
+    border-radius: 4px;
+    background-color: transparent;
+
+    /* rotateZ() forces the layer into compositing mode.
+    Slider thumbs are small, so forcing a compositing layer is inexpensive,
+       and it keeps the slider from having to repaint while sliding. */
+    -webkit-transform: rotateZ(0);
+    background-image: -webkit-linear-gradient(
+        left,
+        rgba(99, 99, 99, 1),
+        rgba(144, 144, 144, 1)
+    );
+    box-shadow: inset -1px 0 0 rgba(255, 255, 255, .5), 0 1px rgba(255, 255, 255, .14);
+}
+video::-webkit-media-controls-volume-slider::-webkit-slider-thumb::-webkit-slider-thumb:active,
+video::-webkit-media-controls-volume-slider::-webkit-slider-thumb:active::-webkit-slider-thumb,
+audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb::-webkit-slider-thumb:active,
+audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb:active::-webkit-slider-thumb {
+    background-image: -webkit-linear-gradient(
+        right top,
+        rgba(160, 160, 160, 1),
+        rgba(221, 221, 221, 1)
+    );
+}
+
+video::-webkit-media-controls-mute-button.muted,
+audio::-webkit-media-controls-mute-button.muted,
+video::-webkit-media-controls-volume-min-button {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 15&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;m 0,9 0,-4 3,0 3,-3 0,10 -3,-3 -3,0 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+}
+
+video::-webkit-media-controls-toggle-closed-captions-button,
+audio::-webkit-media-controls-toggle-closed-captions-button {
+    width: 16px;
+    height: 16px;
+    margin: 0 7px;
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 102 105&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.46875&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.46875&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.53125&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.53125&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M98.766,43.224c0-23.163-21.775-41.94-48.637-41.94c-26.859,0-48.635,18.777-48.635,41.94c0,18.266,13.546,33.796,32.444,39.549c1.131,8.356,26.037,24.255,22.864,19.921c-4.462-6.096-5.159-13.183-5.07-17.566C77.85,84.397,98.766,65.923,98.766,43.224z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+    outline: 0;
+}
+
+video::-webkit-media-controls-closed-captions-container,
+audio::-webkit-media-controls-closed-captions-container {
+    -webkit-appearance: media-closed-captions-container;
+    position: absolute;
+    display: block;
+    right: 38px;
+    bottom: 29px;
+    max-width: calc(100% - 48px); /* right + 10px */
+    max-height: calc(100% - 39px); /* bottom + 10px */
+    overflow-x: hidden;
+    overflow-y: scroll;
+    background-color: rgba(0, 0, 0, 0.85);
+    border: 3px solid rgba(128, 128, 128, 0.75);
+    border-radius: 10px;
+    cursor: default;
+    z-index: 2;
+    text-align: initial;
+}
+
+video::-webkit-media-controls-closed-captions-container .list,
+audio::-webkit-media-controls-closed-captions-container .list {
+    display: block;
+    font-family: &quot;Helvetica Bold&quot;, Helvetica, sans-serif;
+    font-size: 10pt;
+    -webkit-user-select: none;
+}
+
+video::-webkit-media-controls-closed-captions-container h3,
+audio::-webkit-media-controls-closed-captions-container h3 {
+    margin: 0;
+    color: rgb(117, 117, 117);
+    text-shadow: 0 1px 0 black;
+    -webkit-margin-start: 23px;
+    padding-top: 4px;
+    font-weight: bold;
+    font-size: 10pt;
+}
+
+video::-webkit-media-controls-closed-captions-container ul,
+audio::-webkit-media-controls-closed-captions-container ul {
+    list-style-type: none;
+    margin: 0 0 4px 0;
+    padding: 0;
+    font-weight: bold;
+}
+
+video::-webkit-media-controls-closed-captions-container li,
+audio::-webkit-media-controls-closed-captions-container li {
+    position: relative;
+    color: white;
+    background-image: none;
+    text-shadow: 0 1px 0 black;
+    margin: 0;
+    padding-left: 37px;
+    padding-right: 35px;
+    padding-top: 0.15em;
+    padding-bottom: 0.2em;
+    box-sizing: border-box;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    border-top: 1px solid transparent;
+    border-bottom: 1px solid transparent;
+}
+
+video::-webkit-media-controls-closed-captions-container li:focus,
+audio::-webkit-media-controls-closed-captions-container li:focus {
+    outline: 0;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(255, 255, 255, 0.3)), color-stop(1, rgba(255, 255, 255, 0.2)));
+}
+
+video::-webkit-media-controls-closed-captions-container li:hover,
+audio::-webkit-media-controls-closed-captions-container li:hover {
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgb(79, 112, 246)), color-stop(1, rgb(26, 68, 243)));
+    border-top: 1px solid rgb(70, 103, 234);
+    border-bottom: 1px solid rgb(3, 54, 229);
+}
+
+video::-webkit-media-controls-closed-captions-container li.selected::before,
+audio::-webkit-media-controls-closed-captions-container li.selected::before {
+    display: block;
+    content: &quot;&quot;;
+    position: absolute;
+    top: 0.25em;
+    width: 1.1em;
+    height: 1.1em;
+    -webkit-margin-start: -20px;
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 300 300&quot;&gt;&lt;polygon fill=&quot;rgb(163, 163, 163)&quot; points=&quot;252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926&quot;/&gt;&lt;/svg&gt;');
+    background-repeat: no-repeat;
+}
+
+video::-webkit-media-controls-closed-captions-container li.selected:hover::before,
+audio::-webkit-media-controls-closed-captions-container li.selected:hover::before {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 300 300&quot;&gt;&lt;polygon fill=&quot;white&quot; points=&quot;252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926&quot;/&gt;&lt;/svg&gt;');
+}
+
+video::-webkit-media-controls-fullscreen-button,
+audio::-webkit-media-controls-fullscreen-button {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 15&quot; transform=&quot;rotate(90,0,0)&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 14,1 m 0,6 -2,-2 -2,2 c 0,0 -1,1 -2,0 -1,-1 0,-2 0,-2 l 2,-2 -2,-2 6,0 z&quot; style=&quot;fill:url(#gradient) &quot;/&gt;&lt;path d=&quot;M 1,14 m 0,-6 2,2 2,-2 c 0,0 1,-1 2,0 1,1 0,2 0,2 l -2,2 2,2 -6,0 z&quot; style=&quot;fill:url(#gradient) &quot;/&gt;&lt;/svg&gt;');
+    margin: 0 7px;
+}
+video::-webkit-media-controls-fullscreen-button.exit,
+audio::-webkit-media-controls-fullscreen-button.exit {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 15 15&quot; transform=&quot;rotate(90,0,0)&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 7,8 m 0,6 -2,-2 -2,2 c 0,0 -1,1 -2,0 -1,-1 0,-2 0,-2 l 2,-2 -2,-2 6,0 z&quot; style=&quot;fill:url(#gradient) &quot;/&gt;&lt;path d=&quot;M 8,7 m 0,-6 2,2 2,-2 c 0,0 1,-1 2,0 1,1 0,2 0,2 l -2,2 2,2 -6,0 z&quot; style=&quot;fill:url(#gradient) &quot;/&gt;&lt;/svg&gt;');
+}
+video::-webkit-media-controls-status-display,
+audio::-webkit-media-controls-status-display {
+    cursor: default;
+    font: -webkit-small-control;
+    font-size: 9px;
+    overflow: hidden;
+    color: white;
+    text-shadow: black 0px 1px 1px;
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    line-height: 25px;
+    text-transform: none;
+    text-indent: 0;
+    text-decoration: none;
+    text-align: left;
+
+    padding: 0 12px;
+
+    -webkit-flex: 1 1 0;
+}
+video::-webkit-media-controls-timeline,
+audio::-webkit-media-controls-timeline {
+    -webkit-appearance: none;
+    -webkit-flex: 1 1 0;
+    height: 9px;
+    margin: 0;
+
+    border-radius: 4.5px;
+    background-color: rgb(74, 74, 74);
+    box-shadow: inset -1px 0 0 rgba(0, 0, 0, .68), 0 1px rgba(255, 255, 255, .08);
+}
+video::-webkit-media-controls-timeline::-webkit-slider-thumb,
+audio::-webkit-media-controls-timeline::-webkit-slider-thumb {
+    -webkit-appearance: none;
+    width:6px;
+    height: 6px;
+    background-color: white;
+
+    /* rotateZ() forces the layer into compositing mode.
+    Slider thumbs are small, so forcing a compositing layer is inexpensive,
+       and it keeps the slider from having to repaint while sliding. */
+    -webkit-transform: translateY(1px) rotateZ(-45deg);
+
+    background-image: -webkit-gradient(
+        linear,
+        left bottom,
+        right top,
+        color-stop(0, rgba(99,  99,  99,  1)),
+        color-stop(1, rgba(144, 144, 144, 1))
+    );
+}
+video::-webkit-media-controls-timeline::-webkit-slider-thumb:active,
+video::-webkit-media-controls-timeline:active::-webkit-slider-thumb,
+audio::-webkit-media-controls-timeline::-webkit-slider-thumb:active,
+audio::-webkit-media-controls-timeline:active::-webkit-slider-thumb,
+ {
+    background-image: -webkit-gradient(
+        linear,
+        left bottom,
+        right top,
+        color-stop(0, rgba(160, 160, 160, 1)),
+        color-stop(1, rgba(221, 221, 221, 1))
+    );
+}
+video::-webkit-media-controls-current-time-display,
+video::-webkit-media-controls-time-remaining-display,
+audio::-webkit-media-controls-current-time-display,
+audio::-webkit-media-controls-time-remaining-display {
+    -webkit-user-select: none;
+    -webkit-flex: 0 0 0;
+    display: -webkit-flex;
+    -webkit-justify-content: center;
+    -webkit-align-items: center;
+    cursor: default;
+    font: -webkit-small-control;
+    font-size: 9px;
+    overflow-y: hidden;
+    overflow-x: hidden;
+    width: 45px;
+    min-width: 45px;
+    color: white;
+    text-shadow: black 0px 1px 1px;
+    letter-spacing: normal;
+    word-spacing: normal;
+    line-height: normal;
+    text-transform: none;
+    text-indent: 0px;
+    text-decoration: none;
+}
+
+video::-webkit-media-controls-timeline-container .hour-long-time,
+audio::-webkit-media-controls-timeline-container .hour-long-time {
+    min-width: 67px;
+}
+
+video::-webkit-media-controls-timeline-container,
+audio::-webkit-media-controls-timeline-container {
+    display: -webkit-flex;
+    -webkit-flex-direction: row;
+    -webkit-align-items: center;
+    -webkit-user-select: none;
+    -webkit-flex: 1 1 0;
+    position: relative;
+    padding: 0;
+}
+
+video::-webkit-media-controls-panel .thumbnail-track,
+audio::-webkit-media-controls-panel .thumbnail-track {
+    position: relative;
+    -webkit-flex: 1 1 0;
+    height: 9px;
+    margin: 0 2px;
+    display: -webkit-flex;
+    -webkit-align-items: stretch;
+    -webkit-flex-direction: column;
+}
+
+video::-webkit-media-controls-panel .thumbnail,
+audio::-webkit-media-controls-panel .thumbnail {
+    position: absolute;
+    opacity: 0;
+    transition: opacity 0.25s linear;
+    bottom: 15px;
+    width: 100px;
+    height: 58px;
+    margin-left: -50px;
+    border: 5px solid black;
+    box-shadow: 0 0 3px white;
+    border-radius: 3px;
+}
+
+video::-webkit-media-controls-panel .thumbnail-image,
+audio::-webkit-media-controls-panel .thumbnail-image {
+    width: 100%;
+    height: 100%;
+}
+
+video::-webkit-media-controls-panel .thumbnail.show,
+audio::-webkit-media-controls-panel .thumbnail.show {
+    opacity: 1;
+}
+
+video::-webkit-media-controls-panel .hidden,
+audio::-webkit-media-controls-panel .hidden {
+    display: none;
+}
+
+/* Full Screen */
+
+/* 
+    Page stylesheets are not allowed to override the style of media
+    controls while in full screen mode, so many if not all the rules
+    defined in this section will be marked as !important to enforce
+    this restriction 
+*/
+
+video:-webkit-full-screen::-webkit-media-controls-panel {
+    -webkit-align-items: flex-start !important;
+    -webkit-justify-content: flex-end !important;
+
+    width: 440px !important;
+    height: 60px !important;
+    margin: 0 auto 50px auto !important;
+    padding-top: 10px !important;
+
+    background: -webkit-linear-gradient(top,
+        rgba(45, 45, 45, .97) 0,
+        rgba(30, 30, 30, .97) 19px,
+        rgba(25, 25, 25, .97) 19px,
+        rgba(25, 25, 25, .97) 20px,
+        rgba(19, 19, 19, .97) 20px,
+        rgba(12, 12, 12, .97) 100%
+    ) !important;
+
+    box-shadow: 
+        inset 0 -1px 1px rgba(0, 0, 0, 0.5),
+        inset 0  1px 0 0px   rgba(255, 255, 255, 0.15),
+        inset 0 -1px 0 0px   rgba(202, 202, 202, 0.09),
+        0  0   0 1px rgba(0, 0, 0, 0.5);
+    border-radius: 8px !important;
+
+    transition: opacity 0.3s linear !important;
+}
+
+video:-webkit-animating-full-screen-transition::-webkit-media-controls-panel {
+    opacity: 0 ! important;
+    transition: opacity 0 ! important;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-panel .volume-box {
+    -webkit-transform: none;
+    opacity: 1;
+    left: 11px;
+    top: 13px;
+    width: 90px;
+    height: 14px;
+    display: -webkit-flex;
+    -webkit-flex-direction: row;
+    -webkit-align-items: center;
+    background-image: none;
+    border: none;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-volume-slider {
+    height: 6px;
+    border-radius: 3px;
+    background-image: -webkit-linear-gradient(top,
+        rgba(16, 16, 16, .300) 0,
+        rgba(9,  9,  9,  .629) 100%
+    );
+    box-shadow: inset -1px 0 0 rgba(0, 0, 0, .68), 0 1px rgba(255, 255, 255, .08);
+}
+
+video:-webkit-full-screen::-webkit-media-controls-volume-slider::-webkit-slider-thumb {
+    width: 10px;
+    height: 10px;
+    border-radius: 5px;
+
+    /* rotateZ() forces the layer into compositing mode.
+    Slider thumbs are small, so forcing a compositing layer is inexpensive,
+       and it keeps the slider from having to repaint while sliding. */
+    -webkit-transform: rotateZ(270deg);
+}
+
+video:-webkit-full-screen::-webkit-media-controls-play-button {
+    position: absolute;
+    
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 21 22&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.478&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.478&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.522&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.522&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 0,0 0,22 8,22 8,0 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;path d=&quot;M 13,0 13,22 21,22 21,0 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+
+    width: 22px;
+    height: 23px;
+    left: 209px;
+    top: 9px;
+    margin: 0;
+    padding: 0;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-play-button.paused {
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 21 22&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.478&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.478&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.522&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.522&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 0,0 21,11 0,22 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+}
+
+video:-webkit-full-screen::-webkit-media-controls-rewind-button {
+    position: absolute;
+    left: 162px;
+    top: 13px;
+    width: 18px;
+    height: 18px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-seek-back-button {
+    position: absolute;
+
+
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 22 15&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 22,0 11,7 22,15 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;path d=&quot;M 11,0 0,7 11,15 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+
+    width: 23px;
+    height: 16px;
+    left: 156px;
+    top: 13px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-return-to-realtime-button {
+    position: absolute;
+    display: -webkit-flex;
+    width: 29px;
+    height: 16px;
+    left: 262px;
+    top: 13px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-seek-forward-button {
+    position: absolute;
+
+    background-image: url('data:image/svg+xml,&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 22 15&quot;&gt;&lt;linearGradient id=&quot;gradient&quot; x2=&quot;0&quot; y2=&quot;100%&quot; gradientUnits=&quot;userSpaceOnUse&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(216, 216, 216)&quot;/&gt;&lt;stop offset=&quot;0.4375&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;stop offset=&quot;0.5&quot; stop-color=&quot;rgb(200, 200, 200)&quot;/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;rgb(208, 208, 208)&quot;/&gt;&lt;/linearGradient&gt;&lt;path d=&quot;M 0,0 11,7 0,15 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;path d=&quot;M 11,0 22,7 11,15 z&quot; fill=&quot;url(#gradient)&quot;/&gt;&lt;/svg&gt;');
+
+    width: 23px;
+    height: 16px;
+    left: 256px;
+    top: 13px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-timeline-container {
+    height: auto;
+    width: 420px;
+    position: absolute;
+    bottom: 9px;
+    left: 8px;
+    right: 8px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-status-display {
+    width: 420px;
+    position: absolute;
+    bottom: 7px;
+    left: 8px;
+    right: 8px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-closed-captions-container {
+    bottom: 114px;
+    right: calc(50% - 183px); /* 183px is 221px (half the media controller's width) minus 38px (the right position of the captions icon). */
+    max-width: calc(50% + 173px); /* right + 10px */
+    max-height: calc(100% - 124px); /* bottom + 10px */
+}
+
+video::-webkit-media-text-track-container {
+    position: relative;
+    width: 100%;
+    overflow: hidden;
+    padding-bottom: 5px;
+
+    text-align: center;
+    color: rgba(255, 255, 255, 1);
+
+    letter-spacing: normal;
+    word-spacing: normal;
+    text-transform: none;
+    text-indent: 0;
+    text-decoration: none;
+    pointer-events: none;
+    -webkit-user-select: none;
+
+    -webkit-flex: 1 1;
+
+    -webkit-line-box-contain: block inline-box replaced;
+}
+
+video::cue {
+    background-color: rgba(0, 0, 0, 0.8);
+}
+
+video::-webkit-media-text-track-display {
+    position: absolute;
+    overflow: hidden;
+    white-space: pre-wrap;
+    -webkit-box-sizing: border-box;
+    font: 22px sans-serif;
+}
+
+video::-webkit-media-text-track-display-backdrop {
+    display: inline-block;
+}
+
+video::cue(:future) {
+    color: gray;
+}
+
+video::-webkit-media-text-track-container b {
+    font-weight: bold;
+}
+
+video::-webkit-media-text-track-container u {
+    text-decoration: underline;
+}
+
+video::-webkit-media-text-track-container i {
+    font-style: italic;
+}
+
+video::-webkit-media-text-track-container .hidden,
+audio::-webkit-media-text-track-container .hidden {
+    display: none;
+}
</ins><span class="cx">Property changes on: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWebCoreModulesmediacontrolsmediaControlsBasejs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js (0 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -0,0 +1,1313 @@
</span><ins>+function createControls(root, video, host)
+{
+    return new Controller(root, video, host);
+};
+
+function Controller(root, video, host)
+{
+    this.video = video;
+    this.root = root;
+    this.host = host;
+    this.controls = {};
+    this.listeners = {};
+    this.isLive = false;
+    this.statusHidden = true;
+
+    this.addVideoListeners();
+    this.createBase();
+    this.createControls();
+    this.updateBase();
+    this.updateControls();
+    this.updateDuration();
+    this.updateProgress();
+    this.updateTime();
+    this.updateReadyState();
+    this.updatePlaying();
+    this.updateThumbnail();
+    this.updateCaptionButton();
+    this.updateCaptionContainer();
+    this.updateFullscreenButton();
+    this.updateVolume();
+    this.updateHasAudio();
+    this.updateHasVideo();
+};
+
+/* Enums */
+Controller.InlineControls = 0;
+Controller.FullScreenControls = 1;
+
+Controller.PlayAfterSeeking = 0;
+Controller.PauseAfterSeeking = 1;
+
+/* Globals */
+Controller.gLastTimelineId = 0;
+
+Controller.prototype = {
+
+    /* Constants */
+    HandledVideoEvents: {
+        loadstart: 'handleLoadStart',
+        error: 'handleError',
+        abort: 'handleAbort',
+        suspend: 'handleSuspend',
+        stalled: 'handleStalled',
+        waiting: 'handleWaiting',
+        emptied: 'handleReadyStateChange',
+        loadedmetadata: 'handleReadyStateChange',
+        loadeddata: 'handleReadyStateChange',
+        canplay: 'handleReadyStateChange',
+        canplaythrough: 'handleReadyStateChange',
+        timeupdate: 'handleTimeUpdate',
+        durationchange: 'handleDurationChange',
+        playing: 'handlePlay',
+        pause: 'handlePause',
+        progress: 'handleProgress',
+        volumechange: 'handleVolumeChange',
+        webkitfullscreenchange: 'handleFullscreenChange',
+        webkitbeginfullscreen: 'handleFullscreenChange',
+        webkitendfullscreen: 'handleFullscreenChange',
+    },
+    HideControlsDelay: 4 * 1000,
+    RewindAmount: 30,
+    MaximumSeekRate: 8,
+    SeekDelay: 1500,
+    ClassNames: {
+        active: 'active',
+        exit: 'exit',
+        failed: 'failed',
+        hidden: 'hidden',
+        hiding: 'hiding',
+        hourLongTime: 'hour-long-time',
+        list: 'list',
+        muteBox: 'mute-box',
+        muted: 'muted',
+        paused: 'paused',
+        playing: 'playing',
+        selected: 'selected',
+        show: 'show',
+        thumbnail: 'thumbnail',
+        thumbnailImage: 'thumbnail-image',
+        thumbnailTrack: 'thumbnail-track',
+        volumeBox: 'volume-box',
+        noVideo: 'no-video',
+        down: 'down',
+        out: 'out',
+    },
+    KeyCodes: {
+        enter: 13,
+        escape: 27,
+        space: 32,
+        pageUp: 33,
+        pageDown: 34,
+        end: 35,
+        home: 36,
+        left: 37,
+        up: 38,
+        right: 39,
+        down: 40
+    },
+
+    extend: function(child)
+    {
+        for (var property in this) {
+            if (!child.hasOwnProperty(property))
+                child[property] = this[property];
+        }
+    },
+
+    UIString: function(developmentString, replaceString, replacementString)
+    {
+        var localized = UIStringTable[developmentString];
+        if (replaceString &amp;&amp; replacementString)
+            return localized.replace(replaceString, replacementString);
+
+        if (localized)
+            return localized;
+
+        console.error(&quot;Localization for string \&quot;&quot; + developmentString + &quot;\&quot; not found.&quot;);
+        return &quot;LOCALIZED STRING NOT FOUND&quot;;
+    },
+
+    listenFor: function(element, eventName, handler, useCapture)
+    {
+        if (typeof useCapture === 'undefined')
+            useCapture = false;
+
+        if (!(this.listeners[eventName] instanceof Array))
+            this.listeners[eventName] = [];
+        this.listeners[eventName].push({element:element, handler:handler, useCapture:useCapture});
+        element.addEventListener(eventName, this, useCapture);
+    },
+
+    stopListeningFor: function(element, eventName, handler, useCapture)
+    {
+        if (typeof useCapture === 'undefined')
+            useCapture = false;
+
+        if (!(this.listeners[eventName] instanceof Array))
+            return;
+
+        this.listeners[eventName] = this.listeners[eventName].filter(function(entry) {
+            return !(entry.element === element &amp;&amp; entry.handler === handler &amp;&amp; entry.useCapture === useCapture);
+        });
+        element.removeEventListener(eventName, this, useCapture);
+    },
+
+    addVideoListeners: function()
+    {
+        for (name in this.HandledVideoEvents) {
+            this.listenFor(this.video, name, this.HandledVideoEvents[name]);
+        };
+
+        /* text tracks */
+        this.listenFor(this.video.textTracks, 'change', this.handleTextTrackChange);
+        this.listenFor(this.video.textTracks, 'addtrack', this.handleTextTrackAdd);
+        this.listenFor(this.video.textTracks, 'removetrack', this.handleTextTrackRemove);
+
+        /* audio tracks */
+        this.listenFor(this.video.audioTracks, 'change', this.updateHasAudio);
+        this.listenFor(this.video.audioTracks, 'addtrack', this.updateHasAudio);
+        this.listenFor(this.video.audioTracks, 'removetrack', this.updateHasAudio);
+
+        /* video tracks */
+        this.listenFor(this.video.videoTracks, 'change', this.updateHasVideo);
+        this.listenFor(this.video.videoTracks, 'addtrack', this.updateHasVideo);
+        this.listenFor(this.video.videoTracks, 'removetrack', this.updateHasVideo);
+
+        /* controls attribute */
+        this.controlsObserver = new MutationObserver(this.handleControlsChange.bind(this));
+        this.controlsObserver.observe(this.video, { attributes: true, attributeFilter: ['controls'] });
+    },
+
+    removeVideoListeners: function()
+    {
+        for (name in this.HandledVideoEvents) {
+            this.stopListeningFor(this.video, name, this.HandledVideoEvents[name]);
+        };
+
+        /* text tracks */
+        this.stopListeningFor(this.video.textTracks, 'change', this.handleTextTrackChange);
+        this.stopListeningFor(this.video.textTracks, 'addtrack', this.handleTextTrackAdd);
+        this.stopListeningFor(this.video.textTracks, 'removetrack', this.handleTextTrackRemove);
+
+        /* audio tracks */
+        this.stopListeningFor(this.video.audioTracks, 'change', this.updateHasAudio);
+        this.stopListeningFor(this.video.audioTracks, 'addtrack', this.updateHasAudio);
+        this.stopListeningFor(this.video.audioTracks, 'removetrack', this.updateHasAudio);
+
+        /* video tracks */
+        this.stopListeningFor(this.video.videoTracks, 'change', this.updateHasVideo);
+        this.stopListeningFor(this.video.videoTracks, 'addtrack', this.updateHasVideo);
+        this.stopListeningFor(this.video.videoTracks, 'removetrack', this.updateHasVideo);
+
+        /* controls attribute */
+        this.controlsObserver.disconnect();
+        delete(this.controlsObserver);
+    },
+
+    handleEvent: function(event)
+    {
+        var preventDefault = false;
+
+        try {
+            if (event.target === this.video) {
+                var handlerName = this.HandledVideoEvents[event.type];
+                var handler = this[handlerName];
+                if (handler &amp;&amp; handler instanceof Function)
+                    handler.call(this, event);
+            }
+
+            if (!(this.listeners[event.type] instanceof Array))
+                return;
+
+            this.listeners[event.type].forEach(function(entry) {
+                if (entry.element === event.currentTarget &amp;&amp; entry.handler instanceof Function)
+                    preventDefault |= entry.handler.call(this, event);
+            }, this);
+        } catch(e) {
+            if (window.console)
+                console.error(e);
+        }
+
+        if (preventDefault) {
+            event.stopPropagation();
+            event.preventDefault();
+        }
+    },
+
+    createBase: function()
+    {
+        var base = this.base = document.createElement('div');
+        base.setAttribute('pseudo', '-webkit-media-controls');
+        this.listenFor(base, 'mousemove', this.handleWrapperMouseMove);
+        this.listenFor(base, 'mouseout', this.handleWrapperMouseOut);
+        if (this.host.textTrackContainer)
+            base.appendChild(this.host.textTrackContainer);
+    },
+
+    shouldHaveAnyUI: function()
+    {
+        return this.shouldHaveControls() || (this.video.textTracks &amp;&amp; this.video.textTracks.length);
+    },
+
+    shouldHaveControls: function()
+    {
+        return this.video.controls || this.isFullScreen();
+    },
+
+    setNeedsTimelineMetricsUpdate: function()
+    {
+        this.timelineMetricsNeedsUpdate = true;
+    },
+
+    updateTimelineMetricsIfNeeded: function()
+    {
+        if (this.timelineMetricsNeedsUpdate) {
+            this.timelineLeft = this.controls.timeline.offsetLeft;
+            this.timelineWidth = this.controls.timeline.offsetWidth;
+            this.timelineHeight = this.controls.timeline.offsetHeight;
+            this.timelineMetricsNeedsUpdate = false;
+        }
+    },
+
+    updateBase: function()
+    {
+        if (this.shouldHaveAnyUI()) {
+            if (!this.base.parentNode) {
+                this.root.appendChild(this.base);
+            }
+        } else {
+            if (this.base.parentNode) {
+                this.base.parentNode.removeChild(this.base);
+            }
+        }
+    },
+
+    createControls: function()
+    {
+        var panelCompositedParent = this.controls.panelCompositedParent = document.createElement('div');
+        panelCompositedParent.setAttribute('pseudo', '-webkit-media-controls-panel-composited-parent');
+
+        var panel = this.controls.panel = document.createElement('div');
+        panel.setAttribute('pseudo', '-webkit-media-controls-panel');
+        panel.setAttribute('aria-label', (this.isAudio() ? this.UIString('Audio Playback') : this.UIString('Video Playback')));
+        panel.setAttribute('role', 'toolbar');
+        this.listenFor(panel, 'mousedown', this.handlePanelMouseDown);
+        this.listenFor(panel, 'transitionend', this.handlePanelTransitionEnd);
+        this.listenFor(panel, 'click', this.handlePanelClick);
+        this.listenFor(panel, 'dblclick', this.handlePanelClick);
+
+        var rewindButton = this.controls.rewindButton = document.createElement('button');
+        rewindButton.setAttribute('pseudo', '-webkit-media-controls-rewind-button');
+        rewindButton.setAttribute('aria-label', this.UIString('Rewind ##sec## Seconds', '##sec##', this.RewindAmount));
+        this.listenFor(rewindButton, 'click', this.handleRewindButtonClicked);
+
+        var seekBackButton = this.controls.seekBackButton = document.createElement('button');
+        seekBackButton.setAttribute('pseudo', '-webkit-media-controls-seek-back-button');
+        seekBackButton.setAttribute('aria-label', this.UIString('Rewind'));
+        this.listenFor(seekBackButton, 'mousedown', this.handleSeekBackMouseDown);
+        this.listenFor(seekBackButton, 'mouseup', this.handleSeekBackMouseUp);
+
+        var seekForwardButton = this.controls.seekForwardButton = document.createElement('button');
+        seekForwardButton.setAttribute('pseudo', '-webkit-media-controls-seek-forward-button');
+        seekForwardButton.setAttribute('aria-label', this.UIString('Fast Forward'));
+        this.listenFor(seekForwardButton, 'mousedown', this.handleSeekForwardMouseDown);
+        this.listenFor(seekForwardButton, 'mouseup', this.handleSeekForwardMouseUp);
+
+        var playButton = this.controls.playButton = document.createElement('button');
+        playButton.setAttribute('pseudo', '-webkit-media-controls-play-button');
+        playButton.setAttribute('aria-label', this.UIString('Play'));
+        this.listenFor(playButton, 'click', this.handlePlayButtonClicked);
+
+        var statusDisplay = this.controls.statusDisplay = document.createElement('div');
+        statusDisplay.setAttribute('pseudo', '-webkit-media-controls-status-display');
+        statusDisplay.classList.add(this.ClassNames.hidden);
+
+        var timelineBox = this.controls.timelineBox = document.createElement('div');
+        timelineBox.setAttribute('pseudo', '-webkit-media-controls-timeline-container');
+
+        var currentTime = this.controls.currentTime = document.createElement('div');
+        currentTime.setAttribute('pseudo', '-webkit-media-controls-current-time-display');
+        currentTime.setAttribute('aria-label', this.UIString('Elapsed'));
+        currentTime.setAttribute('role', 'timer');
+
+        var timeline = this.controls.timeline = document.createElement('input');
+        this.timelineID = ++Controller.gLastTimelineId;
+        timeline.setAttribute('pseudo', '-webkit-media-controls-timeline');
+        timeline.setAttribute('aria-label', this.UIString('Duration'));
+        timeline.style.backgroundImage = '-webkit-canvas(timeline-' + this.timelineID + ')';
+        timeline.type = 'range';
+        this.listenFor(timeline, 'input', this.handleTimelineChange);
+        this.listenFor(timeline, 'mouseover', this.handleTimelineMouseOver);
+        this.listenFor(timeline, 'mouseout', this.handleTimelineMouseOut);
+        this.listenFor(timeline, 'mousemove', this.handleTimelineMouseMove);
+        this.listenFor(timeline, 'mousedown', this.handleTimelineMouseDown);
+        this.listenFor(timeline, 'mouseup', this.handleTimelineMouseUp);
+        timeline.step = .01;
+
+        var thumbnailTrack = this.controls.thumbnailTrack = document.createElement('div');
+        thumbnailTrack.classList.add(this.ClassNames.thumbnailTrack);
+
+        var thumbnail = this.controls.thumbnail = document.createElement('div');
+        thumbnail.classList.add(this.ClassNames.thumbnail);
+
+        var thumbnailImage = this.controls.thumbnailImage = document.createElement('img');
+        thumbnailImage.classList.add(this.ClassNames.thumbnailImage);
+
+        var remainingTime = this.controls.remainingTime = document.createElement('div');
+        remainingTime.setAttribute('pseudo', '-webkit-media-controls-time-remaining-display');
+        remainingTime.setAttribute('aria-label', this.UIString('Remaining'));
+        remainingTime.setAttribute('role', 'timer');
+
+        var muteBox = this.controls.muteBox = document.createElement('div');
+        muteBox.classList.add(this.ClassNames.muteBox);
+
+        var muteButton = this.controls.muteButton = document.createElement('button');
+        muteButton.setAttribute('pseudo', '-webkit-media-controls-mute-button');
+        muteButton.setAttribute('aria-label', this.UIString('Mute'));
+        this.listenFor(muteButton, 'click', this.handleMuteButtonClicked);
+
+        var minButton = this.controls.minButton = document.createElement('button');
+        minButton.setAttribute('pseudo', '-webkit-media-controls-volume-min-button');
+        minButton.setAttribute('aria-label', this.UIString('Minimum Volume'));
+        this.listenFor(minButton, 'click', this.handleMinButtonClicked);
+
+        var maxButton = this.controls.maxButton = document.createElement('button');
+        maxButton.setAttribute('pseudo', '-webkit-media-controls-volume-max-button');
+        maxButton.setAttribute('aria-label', this.UIString('Maximum Volume'));
+        this.listenFor(maxButton, 'click', this.handleMaxButtonClicked);
+
+        var volumeBox = this.controls.volumeBox = document.createElement('div');
+        volumeBox.setAttribute('pseudo', '-webkit-media-controls-volume-slider-container');
+        volumeBox.classList.add(this.ClassNames.volumeBox);
+
+        var volume = this.controls.volume = document.createElement('input');
+        volume.setAttribute('pseudo', '-webkit-media-controls-volume-slider');
+        volume.setAttribute('aria-label', this.UIString('Volume'));
+        volume.type = 'range';
+        volume.min = 0;
+        volume.max = 1;
+        volume.step = .01;
+        this.listenFor(volume, 'change', this.handleVolumeSliderChange);
+
+        var captionButton = this.controls.captionButton = document.createElement('button');
+        captionButton.setAttribute('pseudo', '-webkit-media-controls-toggle-closed-captions-button');
+        captionButton.setAttribute('aria-label', this.UIString('Captions'));
+        captionButton.setAttribute('aria-haspopup', 'true');
+        this.listenFor(captionButton, 'click', this.handleCaptionButtonClicked);
+
+        var fullscreenButton = this.controls.fullscreenButton = document.createElement('button');
+        fullscreenButton.setAttribute('pseudo', '-webkit-media-controls-fullscreen-button');
+        fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen'));
+        this.listenFor(fullscreenButton, 'click', this.handleFullscreenButtonClicked);
+    },
+
+    setControlsType: function(type)
+    {
+        if (type === this.controlsType)
+            return;
+        this.controlsType = type;
+
+        this.reconnectControls();
+    },
+
+    setIsLive: function(live)
+    {
+        if (live === this.isLive)
+            return;
+        this.isLive = live;
+
+        this.updateStatusDisplay();
+
+        this.reconnectControls();
+    },
+
+    reconnectControls: function()
+    {
+        this.disconnectControls();
+
+        if (this.controlsType === Controller.InlineControls)
+            this.configureInlineControls();
+        else if (this.controlsType == Controller.FullScreenControls)
+            this.configureFullScreenControls();
+
+        if (this.shouldHaveControls())
+            this.addControls();
+    },
+
+    disconnectControls: function(event)
+    {
+        for (item in this.controls) {
+            var control = this.controls[item];
+            if (control &amp;&amp; control.parentNode)
+                control.parentNode.removeChild(control);
+       }
+    },
+
+    configureInlineControls: function()
+    {
+        if (!this.isLive)
+            this.controls.panel.appendChild(this.controls.rewindButton);
+        this.controls.panel.appendChild(this.controls.playButton);
+        this.controls.panel.appendChild(this.controls.statusDisplay);
+        if (!this.isLive) {
+            this.controls.panel.appendChild(this.controls.timelineBox);
+            this.controls.timelineBox.appendChild(this.controls.currentTime);
+            this.controls.timelineBox.appendChild(this.controls.thumbnailTrack);
+            this.controls.thumbnailTrack.appendChild(this.controls.timeline);
+            this.controls.thumbnailTrack.appendChild(this.controls.thumbnail);
+            this.controls.thumbnail.appendChild(this.controls.thumbnailImage);
+            this.controls.timelineBox.appendChild(this.controls.remainingTime);
+        }
+        this.controls.panel.appendChild(this.controls.muteBox);
+        this.controls.muteBox.appendChild(this.controls.volumeBox);
+        this.controls.volumeBox.appendChild(this.controls.volume);
+        this.controls.muteBox.appendChild(this.controls.muteButton);
+        this.controls.panel.appendChild(this.controls.captionButton);
+        if (!this.isAudio())
+            this.controls.panel.appendChild(this.controls.fullscreenButton);
+
+        this.controls.panel.style.removeProperty('left');
+        this.controls.panel.style.removeProperty('top');
+        this.controls.panel.style.removeProperty('bottom');
+    },
+
+    configureFullScreenControls: function()
+    {
+        this.controls.panel.appendChild(this.controls.volumeBox);
+        this.controls.volumeBox.appendChild(this.controls.minButton);
+        this.controls.volumeBox.appendChild(this.controls.volume);
+        this.controls.volumeBox.appendChild(this.controls.maxButton);
+        this.controls.panel.appendChild(this.controls.seekBackButton);
+        this.controls.panel.appendChild(this.controls.playButton);
+        this.controls.panel.appendChild(this.controls.seekForwardButton);
+        this.controls.panel.appendChild(this.controls.captionButton);
+        if (!this.isAudio())
+            this.controls.panel.appendChild(this.controls.fullscreenButton);
+        if (!this.isLive) {
+            this.controls.panel.appendChild(this.controls.timelineBox);
+            this.controls.timelineBox.appendChild(this.controls.currentTime);
+            this.controls.timelineBox.appendChild(this.controls.thumbnailTrack);
+            this.controls.thumbnailTrack.appendChild(this.controls.timeline);
+            this.controls.thumbnailTrack.appendChild(this.controls.thumbnail);
+            this.controls.thumbnail.appendChild(this.controls.thumbnailImage);
+            this.controls.timelineBox.appendChild(this.controls.remainingTime);
+        } else
+            this.controls.panel.appendChild(this.controls.statusDisplay);
+    },
+
+    updateControls: function()
+    {
+        if (this.isFullScreen())
+            this.setControlsType(Controller.FullScreenControls);
+        else
+            this.setControlsType(Controller.InlineControls);
+
+        this.setNeedsTimelineMetricsUpdate();
+    },
+
+    updateStatusDisplay: function(event)
+    {
+        if (this.video.error !== null)
+            this.controls.statusDisplay.innerText = this.UIString('Error');
+        else if (this.isLive &amp;&amp; this.video.readyState &gt;= HTMLMediaElement.HAVE_CURRENT_DATA)
+            this.controls.statusDisplay.innerText = this.UIString('Live Broadcast');
+        else if (this.video.networkState === HTMLMediaElement.NETWORK_LOADING)
+            this.controls.statusDisplay.innerText = this.UIString('Loading');
+        else
+            this.controls.statusDisplay.innerText = '';
+
+        this.setStatusHidden(!this.isLive &amp;&amp; this.video.readyState &gt; HTMLMediaElement.HAVE_NOTHING &amp;&amp; !this.video.error);
+    },
+
+    handleLoadStart: function(event)
+    {
+        this.updateStatusDisplay();
+        this.updateProgress();
+    },
+
+    handleError: function(event)
+    {
+        this.updateStatusDisplay();
+    },
+
+    handleAbort: function(event)
+    {
+        this.updateStatusDisplay();
+    },
+
+    handleSuspend: function(event)
+    {
+        this.updateStatusDisplay();
+    },
+
+    handleStalled: function(event)
+    {
+        this.updateStatusDisplay();
+        this.updateProgress();
+    },
+
+    handleWaiting: function(event)
+    {
+        this.updateStatusDisplay();
+    },
+
+    handleReadyStateChange: function(event)
+    {
+        this.updateReadyState();
+        this.updateDuration();
+        this.updateCaptionButton();
+        this.updateCaptionContainer();
+        this.updateFullscreenButton();
+        this.updateProgress();
+    },
+
+    handleTimeUpdate: function(event)
+    {
+        if (!this.scrubbing)
+            this.updateTime();
+    },
+
+    handleDurationChange: function(event)
+    {
+        this.updateDuration();
+        this.updateTime();
+        this.updateProgress();
+    },
+
+    handlePlay: function(event)
+    {
+        this.setPlaying(true);
+    },
+
+    handlePause: function(event)
+    {
+        this.setPlaying(false);
+    },
+
+    handleProgress: function(event)
+    {
+        this.updateProgress();
+    },
+
+    handleVolumeChange: function(event)
+    {
+        this.updateVolume();
+    },
+
+    handleTextTrackChange: function(event)
+    {
+        this.updateCaptionContainer();
+    },
+
+    handleTextTrackAdd: function(event)
+    {
+        var track = event.track;
+
+        if (this.trackHasThumbnails(track) &amp;&amp; track.mode === 'disabled')
+            track.mode = 'hidden';
+
+        this.updateThumbnail();
+        this.updateCaptionButton();
+        this.updateCaptionContainer();
+    },
+
+    handleTextTrackRemove: function(event)
+    {
+        this.updateThumbnail();
+        this.updateCaptionButton();
+        this.updateCaptionContainer();
+    },
+
+    isFullScreen: function()
+    {
+        return this.video.webkitDisplayingFullscreen;
+    },
+
+    handleFullscreenChange: function(event)
+    {
+        this.updateBase();
+        this.updateControls();
+
+        if (this.isFullScreen()) {
+            this.controls.fullscreenButton.classList.add(this.ClassNames.exit);
+            this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Exit Full Screen'));
+            this.host.enteredFullscreen();
+        } else {
+            this.controls.fullscreenButton.classList.remove(this.ClassNames.exit);
+            this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen'));
+            this.host.exitedFullscreen();
+        }
+    },
+
+    handleWrapperMouseMove: function(event)
+    {
+        this.showControls();
+        this.resetHideControlsTimer();
+
+        if (!this.isDragging)
+            return;
+        var delta = new WebKitPoint(event.clientX - this.initialDragLocation.x, event.clientY - this.initialDragLocation.y);
+        this.controls.panel.style.left = this.initialOffset.x + delta.x + 'px';
+        this.controls.panel.style.top = this.initialOffset.y + delta.y + 'px';
+        event.stopPropagation()
+    },
+
+    handleWrapperMouseOut: function(event)
+    {
+        this.hideControls();
+        this.clearHideControlsTimer();
+    },
+
+    handleWrapperMouseUp: function(event)
+    {
+        this.isDragging = false;
+        this.stopListeningFor(this.base, 'mouseup', 'handleWrapperMouseUp', true);
+    },
+
+    handlePanelMouseDown: function(event)
+    {
+        if (event.target != this.controls.panel)
+            return;
+
+        if (!this.isFullScreen())
+            return;
+
+        this.listenFor(this.base, 'mouseup', this.handleWrapperMouseUp, true);
+        this.isDragging = true;
+        this.initialDragLocation = new WebKitPoint(event.clientX, event.clientY);
+        this.initialOffset = new WebKitPoint(
+            parseInt(this.controls.panel.style.left) | 0,
+            parseInt(this.controls.panel.style.top) | 0
+        );
+    },
+
+    handlePanelTransitionEnd: function(event)
+    {
+        var opacity = window.getComputedStyle(this.controls.panel).opacity;
+        if (parseInt(opacity) &gt; 0)
+            this.controls.panel.classList.remove(this.ClassNames.hidden);
+        else
+            this.controls.panel.classList.add(this.ClassNames.hidden);
+    },
+
+    handlePanelClick: function(event)
+    {
+        // Prevent clicks in the panel from playing or pausing the video in a MediaDocument.
+        event.preventDefault();
+    },
+
+    handleRewindButtonClicked: function(event)
+    {
+        var newTime = Math.max(
+                               this.video.currentTime - this.RewindAmount,
+                               this.video.seekable.start(0));
+        this.video.currentTime = newTime;
+        return true;
+    },
+
+    canPlay: function()
+    {
+        return this.video.paused || this.video.ended || this.video.readyState &lt; HTMLMediaElement.HAVE_METADATA;
+    },
+
+    handlePlayButtonClicked: function(event)
+    {
+        if (this.canPlay())
+            this.video.play();
+        else
+            this.video.pause();
+        return true;
+    },
+
+    handleTimelineChange: function(event)
+    {
+        this.video.fastSeek(this.controls.timeline.value);
+    },
+
+    handleTimelineDown: function(event)
+    {
+        this.controls.thumbnail.classList.add(this.ClassNames.show);
+    },
+
+    handleTimelineUp: function(event)
+    {
+        this.controls.thumbnail.classList.remove(this.ClassNames.show);
+    },
+
+    handleTimelineMouseOver: function(event)
+    {
+        this.controls.thumbnail.classList.add(this.ClassNames.show);
+    },
+
+    handleTimelineMouseOut: function(event)
+    {
+        this.controls.thumbnail.classList.remove(this.ClassNames.show);
+    },
+
+    handleTimelineMouseMove: function(event)
+    {
+        if (this.controls.thumbnail.classList.contains(this.ClassNames.hidden))
+            return;
+
+        this.updateTimelineMetricsIfNeeded();
+        this.controls.thumbnail.classList.add(this.ClassNames.show);
+        var localPoint = webkitConvertPointFromPageToNode(this.controls.timeline, new WebKitPoint(event.clientX, event.clientY));
+        var percent = (localPoint.x - this.timelineLeft) / this.timelineWidth;
+        percent = Math.max(Math.min(1, percent), 0);
+        this.controls.thumbnail.style.left = percent * 100 + '%';
+
+        var thumbnailTime = percent * this.video.duration;
+        for (var i = 0; i &lt; this.video.textTracks.length; ++i) {
+            var track = this.video.textTracks[i];
+            if (!this.trackHasThumbnails(track))
+                continue;
+
+            if (!track.cues)
+                continue;
+
+            for (var j = 0; j &lt; track.cues.length; ++j) {
+                var cue = track.cues[j];
+                if (thumbnailTime &gt;= cue.startTime &amp;&amp; thumbnailTime &lt; cue.endTime) {
+                    this.controls.thumbnailImage.src = cue.text;
+                    return;
+                }
+            }
+        }
+    },
+
+    handleTimelineMouseDown: function(event)
+    {
+        this.scrubbing = true;
+    },
+
+    handleTimelineMouseUp: function(event)
+    {
+        this.scrubbing = false;
+
+        // Do a precise seek when we lift the mouse:
+        this.video.currentTime = this.controls.timeline.value;
+    },
+
+    handleMuteButtonClicked: function(event)
+    {
+        this.video.muted = !this.video.muted;
+        if (this.video.muted)
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Unmute'));
+        return true;
+    },
+
+    handleMinButtonClicked: function(event)
+    {
+        if (this.video.muted) {
+            this.video.muted = false;
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute'));
+        }
+        this.video.volume = 0;
+        return true;
+    },
+
+    handleMaxButtonClicked: function(event)
+    {
+        if (this.video.muted) {
+            this.video.muted = false;
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute'));
+        }
+        this.video.volume = 1;
+    },
+
+    handleVolumeSliderChange: function(event)
+    {
+        if (this.video.muted) {
+            this.video.muted = false;
+            this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute'));
+        }
+        this.video.volume = this.controls.volume.value;
+    },
+
+    handleCaptionButtonClicked: function(event)
+    {
+        if (this.captionMenu)
+            this.destroyCaptionMenu();
+        else
+            this.buildCaptionMenu();
+        return true;
+    },
+
+    updateFullscreenButton: function()
+    {
+        this.controls.fullscreenButton.classList.toggle(this.ClassNames.hidden, !this.video.webkitSupportsFullscreen);
+    },
+
+    handleFullscreenButtonClicked: function(event)
+    {
+        if (this.isFullScreen())
+            this.video.webkitExitFullscreen();
+        else
+            this.video.webkitEnterFullscreen();
+        return true;
+    },
+
+    handleControlsChange: function()
+    {
+        try {
+            this.updateBase();
+
+            if (this.shouldHaveControls())
+                this.addControls();
+            else
+                this.removeControls();
+        } catch(e) {
+            if (window.console)
+                console.error(e);
+        }
+    },
+
+    nextRate: function()
+    {
+        return Math.min(this.MaximumSeekRate, Math.abs(this.video.playbackRate * 2));
+    },
+
+    handleSeekBackMouseDown: function(event)
+    {
+        this.actionAfterSeeking = (this.canPlay() ? Controller.PauseAfterSeeking : Controller.PlayAfterSeeking);
+        this.video.play();
+        this.video.playbackRate = this.nextRate() * -1;
+        this.seekInterval = setInterval(this.seekBackFaster.bind(this), this.SeekDelay);
+    },
+
+    seekBackFaster: function()
+    {
+        this.video.playbackRate = this.nextRate() * -1;
+    },
+
+    handleSeekBackMouseUp: function(event)
+    {
+        this.video.playbackRate = this.video.defaultPlaybackRate;
+        if (this.actionAfterSeeking === Controller.PauseAfterSeeking)
+            this.video.pause();
+        else if (this.actionAfterSeeking === Controller.PlayAfterSeeking)
+            this.video.play();
+        if (this.seekInterval)
+            clearInterval(this.seekInterval);
+    },
+
+    handleSeekForwardMouseDown: function(event)
+    {
+        this.actionAfterSeeking = (this.canPlay() ? Controller.PauseAfterSeeking : Controller.PlayAfterSeeking);
+        this.video.play();
+        this.video.playbackRate = this.nextRate();
+        this.seekInterval = setInterval(this.seekForwardFaster.bind(this), this.SeekDelay);
+    },
+
+    seekForwardFaster: function()
+    {
+        this.video.playbackRate = this.nextRate();
+    },
+
+    handleSeekForwardMouseUp: function(event)
+    {
+        this.video.playbackRate = this.video.defaultPlaybackRate;
+        if (this.actionAfterSeeking === Controller.PauseAfterSeeking)
+            this.video.pause();
+        else if (this.actionAfterSeeking === Controller.PlayAfterSeeking)
+            this.video.play();
+        if (this.seekInterval)
+            clearInterval(this.seekInterval);
+    },
+
+    updateDuration: function()
+    {
+        var duration = this.video.duration;
+        this.controls.timeline.min = 0;
+        this.controls.timeline.max = duration;
+
+        this.setIsLive(duration === Number.POSITIVE_INFINITY);
+
+        this.controls.currentTime.classList.toggle(this.ClassNames.hourLongTime, duration &gt;= 60*60);
+        this.controls.remainingTime.classList.toggle(this.ClassNames.hourLongTime, duration &gt;= 60*60);
+    },
+
+    progressFillStyle: function(context)
+    {
+        var height = this.timelineHeight;
+        var gradient = context.createLinearGradient(0, 0, 0, height);
+        gradient.addColorStop(0, 'rgb(2, 2, 2)');
+        gradient.addColorStop(1, 'rgb(23, 23, 23)');
+        return gradient;
+    },
+
+    updateProgress: function()
+    {
+        this.updateTimelineMetricsIfNeeded();
+
+        var width = this.timelineWidth;
+        var height = this.timelineHeight;
+
+        var context = document.getCSSCanvasContext('2d', 'timeline-' + this.timelineID, width, height);
+        context.clearRect(0, 0, width, height);
+
+        context.fillStyle = this.progressFillStyle(context);
+
+        var duration = this.video.duration;
+        var buffered = this.video.buffered;
+        for (var i = 0, end = buffered.length; i &lt; end; ++i) {
+            var startTime = buffered.start(i);
+            var endTime = buffered.end(i);
+
+            var startX = width * startTime / duration;
+            var endX = width * endTime / duration;
+            context.fillRect(startX, 0, endX - startX, height);
+        }
+    },
+
+    formatTime: function(time)
+    {
+        if (isNaN(time))
+            time = 0;
+        var absTime = Math.abs(time);
+        var intSeconds = Math.floor(absTime % 60).toFixed(0);
+        var intMinutes = Math.floor((absTime / 60) % 60).toFixed(0);
+        var intHours = Math.floor(absTime / (60 * 60)).toFixed(0);
+        var sign = time &lt; 0 ? '-' : String();
+
+        if (intHours &gt; 0)
+            return sign + intHours + ':' + String('00' + intMinutes).slice(-2) + &quot;:&quot; + String('00' + intSeconds).slice(-2);
+
+        return sign + String('00' + intMinutes).slice(-2) + &quot;:&quot; + String('00' + intSeconds).slice(-2)
+    },
+
+    updatePlaying: function()
+    {
+        this.setPlaying(!this.canPlay());
+    },
+
+    setPlaying: function(isPlaying)
+    {
+        if (this.isPlaying === isPlaying)
+            return;
+        this.isPlaying = isPlaying;
+
+        if (!isPlaying) {
+            this.controls.panel.classList.add(this.ClassNames.paused);
+            this.controls.playButton.classList.add(this.ClassNames.paused);
+            this.controls.playButton.setAttribute('aria-label', this.UIString('Play'));
+        } else {
+            this.controls.panel.classList.remove(this.ClassNames.paused);
+            this.controls.playButton.classList.remove(this.ClassNames.paused);
+            this.controls.playButton.setAttribute('aria-label', this.UIString('Pause'));
+
+            this.hideControls();
+            this.resetHideControlsTimer();
+        }
+    },
+
+    showControls: function()
+    {
+        this.controls.panel.classList.add(this.ClassNames.show);
+        this.controls.panel.classList.remove(this.ClassNames.hidden);
+
+        this.setNeedsTimelineMetricsUpdate();
+    },
+
+    hideControls: function()
+    {
+        this.controls.panel.classList.remove(this.ClassNames.show);
+    },
+
+    controlsAreHidden: function()
+    {
+        return !this.controls.panel.classList.contains(this.ClassNames.show) || this.controls.panel.classList.contains(this.ClassNames.hidden);
+    },
+
+    removeControls: function()
+    {
+        if (this.controls.panel.parentNode)
+            this.controls.panel.parentNode.removeChild(this.controls.panel);
+        this.destroyCaptionMenu();
+    },
+
+    addControls: function()
+    {
+        this.base.appendChild(this.controls.panelCompositedParent);
+        this.controls.panelCompositedParent.appendChild(this.controls.panel);
+        this.setNeedsTimelineMetricsUpdate();
+    },
+
+    updateTime: function()
+    {
+        var currentTime = this.video.currentTime;
+        var timeRemaining = currentTime - this.video.duration;
+        this.controls.currentTime.innerText = this.formatTime(currentTime);
+        this.controls.timeline.value = this.video.currentTime;
+        this.controls.remainingTime.innerText = this.formatTime(timeRemaining);
+    },
+
+    updateReadyState: function()
+    {
+        this.updateStatusDisplay();
+    },
+
+    setStatusHidden: function(hidden)
+    {
+        if (this.statusHidden === hidden)
+            return;
+
+        this.statusHidden = hidden;
+
+        if (hidden) {
+            this.controls.statusDisplay.classList.add(this.ClassNames.hidden);
+            this.controls.currentTime.classList.remove(this.ClassNames.hidden);
+            this.controls.timeline.classList.remove(this.ClassNames.hidden);
+            this.controls.remainingTime.classList.remove(this.ClassNames.hidden);
+            this.setNeedsTimelineMetricsUpdate();
+        } else {
+            this.controls.statusDisplay.classList.remove(this.ClassNames.hidden);
+            this.controls.currentTime.classList.add(this.ClassNames.hidden);
+            this.controls.timeline.classList.add(this.ClassNames.hidden);
+            this.controls.remainingTime.classList.add(this.ClassNames.hidden);
+        }
+    },
+
+    trackHasThumbnails: function(track)
+    {
+        return track.kind === 'thumbnails' || (track.kind === 'metadata' &amp;&amp; track.label === 'thumbnails');
+    },
+
+    updateThumbnail: function()
+    {
+        for (var i = 0; i &lt; this.video.textTracks.length; ++i) {
+            var track = this.video.textTracks[i];
+            if (this.trackHasThumbnails(track)) {
+                this.controls.thumbnail.classList.remove(this.ClassNames.hidden);
+                return;
+            }
+        }
+
+        this.controls.thumbnail.classList.add(this.ClassNames.hidden);
+    },
+
+    updateCaptionButton: function()
+    {
+        if (this.video.webkitHasClosedCaptions)
+            this.controls.captionButton.classList.remove(this.ClassNames.hidden);
+        else
+            this.controls.captionButton.classList.add(this.ClassNames.hidden);
+    },
+
+    updateCaptionContainer: function()
+    {
+        if (!this.host.textTrackContainer)
+            return;
+
+        var hasClosedCaptions = this.video.webkitHasClosedCaptions;
+        var hasHiddenClass = this.host.textTrackContainer.classList.contains(this.ClassNames.hidden);
+
+        if (hasClosedCaptions &amp;&amp; hasHiddenClass)
+            this.host.textTrackContainer.classList.remove(this.ClassNames.hidden);
+        else if (!hasClosedCaptions &amp;&amp; !hasHiddenClass)
+            this.host.textTrackContainer.classList.add(this.ClassNames.hidden);
+
+        this.updateBase();
+        this.host.updateTextTrackContainer();
+    },
+
+    buildCaptionMenu: function()
+    {
+        var tracks = this.host.sortedTrackListForMenu(this.video.textTracks);
+        if (!tracks || !tracks.length)
+            return;
+
+        this.captionMenu = document.createElement('div');
+        this.captionMenu.setAttribute('pseudo', '-webkit-media-controls-closed-captions-container');
+        this.base.appendChild(this.captionMenu);
+        this.captionMenuItems = [];
+
+        var offItem = this.host.captionMenuOffItem;
+        var automaticItem = this.host.captionMenuAutomaticItem;
+        var displayMode = this.host.captionDisplayMode;
+
+        var list = document.createElement('div');
+        this.captionMenu.appendChild(list);
+        list.classList.add(this.ClassNames.list);
+
+        var heading = document.createElement('h3');
+        heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label
+        list.appendChild(heading);
+        heading.innerText = this.UIString('Subtitles');
+
+        var ul = document.createElement('ul');
+        ul.setAttribute('role', 'menu');
+        ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading');
+        list.appendChild(ul);
+
+        for (var i = 0; i &lt; tracks.length; ++i) {
+            var menuItem = document.createElement('li');
+            menuItem.setAttribute('role', 'menuitemradio');
+            menuItem.setAttribute('tabindex', '-1');
+            this.captionMenuItems.push(menuItem);
+            this.listenFor(menuItem, 'click', this.captionItemSelected);
+            this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp);
+            ul.appendChild(menuItem);
+
+            var track = tracks[i];
+            menuItem.innerText = this.host.displayNameForTrack(track);
+            menuItem.track = track;
+
+            if (track === offItem) {
+                var offMenu = menuItem;
+                continue;
+            }
+
+            if (track === automaticItem) {
+                if (displayMode === 'automatic') {
+                    menuItem.classList.add(this.ClassNames.selected);
+                    menuItem.setAttribute('tabindex', '0');
+                    menuItem.setAttribute('aria-checked', 'true');
+                }
+                continue;
+            }
+
+            if (displayMode != 'automatic' &amp;&amp; track.mode === 'showing') {
+                var trackMenuItemSelected = true;
+                menuItem.classList.add(this.ClassNames.selected);
+                menuItem.setAttribute('tabindex', '0');
+                menuItem.setAttribute('aria-checked', 'true');
+            }
+
+        }
+
+        if (offMenu &amp;&amp; displayMode === 'forced-only' &amp;&amp; !trackMenuItemSelected) {
+            offMenu.classList.add(this.ClassNames.selected);
+            menuItem.setAttribute('tabindex', '0');
+            menuItem.setAttribute('aria-checked', 'true');
+        }
+        
+        // focus first selected menuitem
+        for (var i = 0, c = this.captionMenuItems.length; i &lt; c; i++) {
+            var item = this.captionMenuItems[i];
+            if (item.classList.contains(this.ClassNames.selected)) {
+                item.focus();
+                break;
+            }
+        }
+        
+    },
+
+    captionItemSelected: function(event)
+    {
+        this.host.setSelectedTextTrack(event.target.track);
+        this.destroyCaptionMenu();
+    },
+
+    focusSiblingCaptionItem: function(event)
+    {
+        var currentItem = event.target;
+        var pendingItem = false;
+        switch(event.keyCode) {
+        case this.KeyCodes.left:
+        case this.KeyCodes.up:
+            pendingItem = currentItem.previousSibling;
+            break;
+        case this.KeyCodes.right:
+        case this.KeyCodes.down:
+            pendingItem = currentItem.nextSibling;
+            break;
+        }
+        if (pendingItem) {
+            currentItem.setAttribute('tabindex', '-1');
+            pendingItem.setAttribute('tabindex', '0');
+            pendingItem.focus();
+        }
+    },
+
+    handleCaptionItemKeyUp: function(event)
+    {
+        switch (event.keyCode) {
+        case this.KeyCodes.enter:
+        case this.KeyCodes.space:
+            this.captionItemSelected(event);
+            break;
+        case this.KeyCodes.escape:
+            this.destroyCaptionMenu();
+            break;
+        case this.KeyCodes.left:
+        case this.KeyCodes.up:
+        case this.KeyCodes.right:
+        case this.KeyCodes.down:
+            this.focusSiblingCaptionItem(event);
+            break;
+        default:
+            return;
+        }
+        // handled
+        event.stopPropagation();
+        event.preventDefault();
+    },
+
+    destroyCaptionMenu: function()
+    {
+        if (!this.captionMenu)
+            return;
+
+        this.captionMenuItems.forEach(function(item){
+            this.stopListeningFor(item, 'click', this.captionItemSelected);
+            this.stopListeningFor(item, 'keyup', this.handleCaptionItemKeyUp);
+        }, this);
+
+        // FKA and AX: focus the trigger before destroying the element with focus
+        if (this.controls.captionButton)
+            this.controls.captionButton.focus();
+
+        if (this.captionMenu.parentNode)
+            this.captionMenu.parentNode.removeChild(this.captionMenu);
+        delete this.captionMenu;
+        delete this.captionMenuItems;
+    },
+
+    updateHasAudio: function()
+    {
+        if (this.video.audioTracks.length)
+            this.controls.muteBox.classList.remove(this.ClassNames.hidden);
+        else
+            this.controls.muteBox.classList.add(this.ClassNames.hidden);
+    },
+
+    updateHasVideo: function()
+    {
+        if (this.video.videoTracks.length)
+            this.controls.panel.classList.remove(this.ClassNames.noVideo);
+        else
+            this.controls.panel.classList.add(this.ClassNames.noVideo);
+    },
+
+    updateVolume: function()
+    {
+        if (this.video.muted || !this.video.volume) {
+            this.controls.muteButton.classList.add(this.ClassNames.muted);
+            this.controls.volume.value = 0;
+        } else {
+            this.controls.muteButton.classList.remove(this.ClassNames.muted);
+            this.controls.volume.value = this.video.volume;
+        }
+    },
+
+    isAudio: function()
+    {
+        return this.video instanceof HTMLAudioElement;
+    },
+
+    clearHideControlsTimer: function()
+    {
+        if (this.hideTimer)
+            clearTimeout(this.hideTimer);
+        this.hideTimer = null;
+    },
+
+    resetHideControlsTimer: function()
+    {
+        if (this.hideTimer)
+            clearTimeout(this.hideTimer);
+        this.hideTimer = setTimeout(this.hideControls.bind(this), this.HideControlsDelay);
+    },
+};
</ins><span class="cx">Property changes on: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWebCorePlatformEflcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformEfl.cmake (173400 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformEfl.cmake        2014-09-08 21:40:08 UTC (rev 173400)
+++ trunk/Source/WebCore/PlatformEfl.cmake        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -278,12 +278,12 @@
</span><span class="cx"> endif ()
</span><span class="cx"> 
</span><span class="cx"> list(APPEND WebCore_USER_AGENT_STYLE_SHEETS
</span><del>-    ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsApple.css
</del><ins>+    ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsBase.css
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx"> set(WebCore_USER_AGENT_SCRIPTS
</span><span class="cx">     ${WEBCORE_DIR}/English.lproj/mediaControlsLocalizedStrings.js
</span><del>-    ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsApple.js
</del><ins>+    ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsBase.js
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx"> set(WebCore_USER_AGENT_SCRIPTS_DEPENDENCIES ${WEBCORE_DIR}/platform/efl/RenderThemeEfl.cpp)
</span></span></pre></div>
<a id="trunkSourceWebCorePlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformGTK.cmake (173400 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformGTK.cmake        2014-09-08 21:40:08 UTC (rev 173400)
+++ trunk/Source/WebCore/PlatformGTK.cmake        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -268,7 +268,7 @@
</span><span class="cx"> 
</span><span class="cx"> set(WebCore_USER_AGENT_SCRIPTS
</span><span class="cx">     ${WEBCORE_DIR}/English.lproj/mediaControlsLocalizedStrings.js
</span><del>-    ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsApple.js
</del><ins>+    ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsBase.js
</ins><span class="cx">     ${WEBCORE_DIR}/Modules/mediacontrols/mediaControlsGtk.js
</span><span class="cx"> )
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformeflRenderThemeEflcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/efl/RenderThemeEfl.cpp (173400 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/efl/RenderThemeEfl.cpp        2014-09-08 21:40:08 UTC (rev 173400)
+++ trunk/Source/WebCore/platform/efl/RenderThemeEfl.cpp        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -1027,14 +1027,14 @@
</span><span class="cx"> #if ENABLE(VIDEO)
</span><span class="cx"> String RenderThemeEfl::mediaControlsStyleSheet()
</span><span class="cx"> {
</span><del>-    return ASCIILiteral(mediaControlsAppleUserAgentStyleSheet);
</del><ins>+    return ASCIILiteral(mediaControlsBaseUserAgentStyleSheet);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String RenderThemeEfl::mediaControlsScript()
</span><span class="cx"> {
</span><span class="cx">     StringBuilder scriptBuilder;
</span><span class="cx">     scriptBuilder.append(mediaControlsLocalizedStringsJavaScript, sizeof(mediaControlsLocalizedStringsJavaScript));
</span><del>-    scriptBuilder.append(mediaControlsAppleJavaScript, sizeof(mediaControlsAppleJavaScript));
</del><ins>+    scriptBuilder.append(mediaControlsBaseJavaScript, sizeof(mediaControlsBaseJavaScript));
</ins><span class="cx">     return scriptBuilder.toString();
</span><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderThemeGtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderThemeGtk.cpp (173400 => 173401)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderThemeGtk.cpp        2014-09-08 21:40:08 UTC (rev 173400)
+++ trunk/Source/WebCore/rendering/RenderThemeGtk.cpp        2014-09-08 22:33:21 UTC (rev 173401)
</span><span class="lines">@@ -1671,7 +1671,7 @@
</span><span class="cx"> {
</span><span class="cx">     StringBuilder scriptBuilder;
</span><span class="cx">     scriptBuilder.append(mediaControlsLocalizedStringsJavaScript, sizeof(mediaControlsLocalizedStringsJavaScript));
</span><del>-    scriptBuilder.append(mediaControlsAppleJavaScript, sizeof(mediaControlsAppleJavaScript));
</del><ins>+    scriptBuilder.append(mediaControlsBaseJavaScript, sizeof(mediaControlsBaseJavaScript));
</ins><span class="cx">     scriptBuilder.append(mediaControlsGtkJavaScript, sizeof(mediaControlsGtkJavaScript));
</span><span class="cx">     return scriptBuilder.toString();
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>