<!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>[209964] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/209964">209964</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2016-12-17 09:18:54 -0800 (Sat, 17 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add implementation for navigator.requestMediaKeySystemAccess()
https://bugs.webkit.org/show_bug.cgi?id=165850

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html

Add an implementation of NavigatorEME::requestMediaKeySystemAccess() as well as the CDM
object on which it depends.

* Modules/encryptedmedia/CDM.cpp: Added.
(WebCore::cdmFactories):
(WebCore::createCDMPrivateForKeySystem):
(WebCore::CDM::registerCDMFactory):
(WebCore::CDM::unregisterCDMFactory):
(WebCore::CDM::supportsKeySystem):
(WebCore::CDM::create):
(WebCore::CDM::CDM):
(WebCore::CDM::getSupportedConfiguration):
(WebCore::CDM::doSupportedConfigurationStep):
(WebCore::CDM::isPersistentType):
(WebCore::CDM::getSupportedCapabilitiesForAudioVideoType):
(WebCore::CDM::getConsentStatus):
* Modules/encryptedmedia/CDM.h: Added.
(WebCore::CDMFactory::~CDMFactory):
(WebCore::CDM::keySystem):
(WebCore::CDM::createWeakPtr):
* Modules/encryptedmedia/CDMPrivate.h: Added.
(WebCore::CDMPrivate::~CDMPrivate):
* Modules/encryptedmedia/NavigatorEME.cpp:
(WebCore::NavigatorEME::requestMediaKeySystemAccess):
(WebCore::tryNextSupportedConfiguration):
* Modules/encryptedmedia/NavigatorEME.h:
* Modules/encryptedmedia/NavigatorEME.idl:

To aid in testing, a new Internals object is added, MockCDMFactory, which can be
controlled by LayoutTests to change the behavior of the Mock objects it creates.

* testing/Internals.cpp:
(WebCore::Internals::registerMockCDM):
* testing/Internals.h:
* testing/Internals.idl:
* testing/MockCDMFactory.cpp: Added.
(WebCore::MockCDMFactory::MockCDMFactory):
(WebCore::MockCDMFactory::~MockCDMFactory):
(WebCore::MockCDMFactory::unregister):
(WebCore::MockCDMFactory::supportsKeySystem):
(WebCore::MockCDMFactory::createCDM):
(WebCore::MockCDM::MockCDM):
(WebCore::MockCDM::supportsInitDataType):
(WebCore::MockCDM::supportsConfiguration):
(WebCore::MockCDM::supportsConfigurationWithRestrictions):
(WebCore::MockCDM::supportsSessionTypeWithConfiguration):
(WebCore::MockCDM::supportsRobustness):
(WebCore::MockCDM::distinctiveIdentifiersRequirement):
(WebCore::MockCDM::persistentStateRequirement):
(WebCore::MockCDM::distinctiveIdentifiersAreUniquePerOriginAndClearable):
* testing/MockCDMFactory.h: Added.
(WebCore::MockCDMFactory::create):
(WebCore::MockCDMFactory::supportedDataTypes):
(WebCore::MockCDMFactory::setSupportedDataTypes):
(WebCore::MockCDMFactory::supportedRobustness):
(WebCore::MockCDMFactory::setSupportedRobustness):
(WebCore::MockCDMFactory::distinctiveIdentifiersRequirement):
(WebCore::MockCDMFactory::setDistinctiveIdentifiersRequirement):
(WebCore::MockCDMFactory::persistentStateRequirement):
(WebCore::MockCDMFactory::setPersistentStateRequirement):
* testing/MockCDMFactory.idl: Added.

Move the MediaKeySessionType definition out of the MediaKeys.idl file and into its own.
Move the MediaKeysRequiriment definition out of the MediaKeySystemConfiguration.idl file
and into its own. Generally fix up the .idl files so that they properly work with their
implementation files.

* Modules/encryptedmedia/MediaKeySessionType.idl: Added.
* Modules/encryptedmedia/MediaKeySystemAccess.cpp:
(WebCore::MediaKeySystemAccess::create):
(WebCore::MediaKeySystemAccess::MediaKeySystemAccess):
(WebCore::MediaKeySystemAccess::keySystem): Deleted.
(WebCore::MediaKeySystemAccess::getConfiguration): Deleted.
* Modules/encryptedmedia/MediaKeySystemAccess.h:
(WebCore::MediaKeySystemAccess::keySystem):
(WebCore::MediaKeySystemAccess::getConfiguration):
(WebCore::MediaKeySystemAccess::create): Deleted.
* Modules/encryptedmedia/MediaKeySystemAccess.idl:
* Modules/encryptedmedia/MediaKeySystemConfiguration.h:
* Modules/encryptedmedia/MediaKeySystemConfiguration.idl:
* Modules/encryptedmedia/MediaKeySystemMediaCapability.idl:
* Modules/encryptedmedia/MediaKeys.idl:
* Modules/encryptedmedia/MediaKeysRequirement.idl: Added.
* Modules/encryptedmedia/MediaKeysRestrictions.h: Added.
* bindings/js/JSMediaKeySystemAccessCustom.cpp: Removed.

As some of these enums are referenced in the Internals project, they need to be exported
from WebCore correctly. Teach the code generator how to export the symbols generated by
enums.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateEnumerationHeaderContent):

Add new files to the project.

* CMakeLists.txt:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:

LayoutTests:

* media/encrypted-media/mock-navigator-requestMediaKeySystemAccess-expected.txt: Added.
* media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html: Added.
* platform/ios-simulator/TestExpectations:
* platform/mac/TestExpectations:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsplatformmacTestExpectations">trunk/LayoutTests/platform/mac/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySystemAccesscpp">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySystemAccessh">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySystemAccessidl">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySystemConfigurationh">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySystemConfigurationidl">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySystemMediaCapabilityidl">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeysidl">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaNavigatorEMEcpp">trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaNavigatorEMEh">trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaNavigatorEMEidl">trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediaencryptedmediamocknavigatorrequestMediaKeySystemAccessexpectedtxt">trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediaencryptedmediamocknavigatorrequestMediaKeySystemAccesshtml">trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMcpp">trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMh">trunk/Source/WebCore/Modules/encryptedmedia/CDM.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMPrivateh">trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySessionTypeidl">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeysRequirementidl">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeysRestrictionsh">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMFactorycpp">trunk/Source/WebCore/testing/MockCDMFactory.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMFactoryh">trunk/Source/WebCore/testing/MockCDMFactory.h</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMFactoryidl">trunk/Source/WebCore/testing/MockCDMFactory.idl</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorebindingsjsJSMediaKeySystemAccessCustomcpp">trunk/Source/WebCore/bindings/js/JSMediaKeySystemAccessCustom.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/LayoutTests/ChangeLog        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-12-17  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Add implementation for navigator.requestMediaKeySystemAccess()
+        https://bugs.webkit.org/show_bug.cgi?id=165850
+
+        Reviewed by Eric Carlson.
+
+        * media/encrypted-media/mock-navigator-requestMediaKeySystemAccess-expected.txt: Added.
+        * media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html: Added.
+        * platform/ios-simulator/TestExpectations:
+        * platform/mac/TestExpectations:
+
</ins><span class="cx"> 2016-12-17  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Cloned CachedResource should not have an empty response
</span></span></pre></div>
<a id="trunkLayoutTestsmediaencryptedmediamocknavigatorrequestMediaKeySystemAccessexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess-expected.txt (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess-expected.txt        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+RUN(internals.initializeMockMediaSource())
+RUN(mock = internals.registerMockCDM())
+RUN(mock.supportedDataTypes = [&quot;mock&quot;])
+
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ] } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.keySystem == 'org.webkit.mock') OK
+EXPECTED (access.getConfiguration().initDataTypes.length == '1') OK
+EXPECTED (access.getConfiguration().initDataTypes[0] == 'mock') OK
+EXPECTED (access.getConfiguration().sessionTypes.length == '1') OK
+EXPECTED (access.getConfiguration().sessionTypes[0] == 'temporary') OK
+EXPECTED (access.getConfiguration().distinctiveIdentifier == 'not-allowed') OK
+EXPECTED (access.getConfiguration().persistentState == 'not-allowed') OK
+
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;unknown/mime; codecs=\&quot;unknown\&quot;&quot; } ] } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise rejected correctly OK
+EXPECTED (exceptionCode.name == 'NotSupportedError') OK
+
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;unknownType&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ] } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise rejected correctly OK
+EXPECTED (exceptionCode.name == 'NotSupportedError') OK
+
+RUN(mock.supportedRobustness = [&quot;high&quot;])
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot;, &quot;robustness&quot;: &quot;high&quot; } ] } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().videoCapabilities.length == '1') OK
+EXPECTED (access.getConfiguration().videoCapabilities[0].robustness == 'high') OK
+
+RUN(mock.supportedRobustness = [&quot;high&quot;])
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot;, &quot;robustness&quot;: &quot;low&quot; } ] } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise rejected correctly OK
+EXPECTED (exceptionCode.name == 'NotSupportedError') OK
+
+RUN(mock.distinctiveIdentifierRequirement = &quot;not-allowed&quot;)
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;distinctiveIdentifier&quot;: &quot;optional&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().distinctiveIdentifier == 'not-allowed') OK
+
+RUN(mock.distinctiveIdentifiersRequirement = &quot;required&quot;)
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;distinctiveIdentifier&quot;: &quot;optional&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().distinctiveIdentifier == 'required') OK
+
+RUN(mock.distinctiveIdentifiersRequirement = &quot;not-allowed&quot;)
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;distinctiveIdentifier&quot;: &quot;required&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise rejected correctly OK
+EXPECTED (exceptionCode.name == 'NotSupportedError') OK
+
+RUN(mock.distinctiveIdentifiersRequirement = &quot;not-allowed&quot;)
+SET capabilities = '[ { &quot;label&quot;: &quot;distinctive-identifiers-required&quot;, &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;distinctiveIdentifier&quot;: &quot;required&quot; }, { &quot;label&quot;: &quot;distinctive-identifiers-not-required&quot;, &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;distinctiveIdentifier&quot;: &quot;optional&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().label == 'distinctive-identifiers-not-required') OK
+EXPECTED (access.getConfiguration().distinctiveIdentifier == 'not-allowed') OK
+
+RUN(mock.persistentStateRequirement = &quot;required&quot;)
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;persistentState&quot;: &quot;optional&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().persistentState == 'required') OK
+
+RUN(mock.persistentStateRequirement = &quot;not-allowed&quot;)
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;persistentState&quot;: &quot;optional&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().persistentState == 'not-allowed') OK
+
+RUN(mock.persistentStateRequirement = &quot;not-allowed&quot;)
+SET capabilities = '[ { &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;persistentState&quot;: &quot;required&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise rejected correctly OK
+EXPECTED (exceptionCode.name == 'NotSupportedError') OK
+
+RUN(mock.persistentStateRequirement = &quot;not-allowed&quot;)
+SET capabilities = '[ { &quot;label&quot;: &quot;persistent-state-required&quot;, &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;persistentState&quot;: &quot;required&quot; }, { &quot;label&quot;: &quot;persistent-state-not-required&quot;, &quot;initDataTypes&quot;: [ &quot;mock&quot; ], &quot;videoCapabilities&quot;: [ { &quot;contentType&quot;: &quot;video/mock; codecs=\&quot;mock\&quot;&quot; } ], &quot;persistentState&quot;: &quot;optional&quot; } ]'
+RUN(promise = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities))
+Promise resolved OK
+EXPECTED (access.getConfiguration().label == 'persistent-state-not-required') OK
+EXPECTED (access.getConfiguration().persistentState == 'not-allowed') OK
+END OF TEST
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediaencryptedmediamocknavigatorrequestMediaKeySystemAccesshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html                                (rev 0)
+++ trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,253 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script src=../video-test.js&gt;&lt;/script&gt;
+    &lt;script type=&quot;text/javascript&quot;&gt;
+    var mock;
+    var promise;
+    var capabilities = {};
+
+    function doTest () 
+    {
+        if (!window.internals) {
+            // failTest(&quot;Internals is required for this test.&quot;)
+            // return;
+        }
+
+        run('internals.initializeMockMediaSource()');
+        run('mock = internals.registerMockCDM()');
+        run('mock.supportedDataTypes = [&quot;mock&quot;]');
+
+        next();
+    }
+
+    function next() {
+        if (!tests.length) {
+            mock.unregister();
+            endTest()
+            return;
+        }
+
+        var nextTest = tests.shift();
+        consoleWrite('');
+        nextTest();
+    }
+
+    function passingTestWithCapabilities(capabilities, success) {
+        testWithCapabilities(capabilities);
+        promise.then(mediaKeySystemAccess =&gt; {
+            logResult(Success, 'Promise resolved');
+            success(mediaKeySystemAccess);
+            next();
+        }, () =&gt; {
+            logResult(Failed, 'Promise rejected');
+            next();
+        });
+    }
+
+    function failingTestWithCapabilities(capabilities, failure) {
+        testWithCapabilities(capabilities);
+        promise.then(() =&gt; {
+            logResult(Failed, 'Promise resolved incorrectly');
+            next();
+        }, exceptionCode =&gt; {
+            logResult(Success, 'Promise rejected correctly');
+            failure(exceptionCode)
+            next();
+        });
+    }
+
+    function testWithCapabilities(capabilities) {
+        window.capabilities = capabilities;
+        consoleWrite(`SET capabilities = '${ JSON.stringify(capabilities, null, 1) }'`);
+        run('promise  = navigator.requestMediaKeySystemAccess(&quot;org.webkit.mock&quot;, capabilities)');
+    }
+
+    tests = [
+        function() {
+            passingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;' }] 
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.keySystem', 'org.webkit.mock');
+                    testExpected('access.getConfiguration().initDataTypes.length', '1');
+                    testExpected('access.getConfiguration().initDataTypes[0]', 'mock');
+                    testExpected('access.getConfiguration().sessionTypes.length', '1');
+                    testExpected('access.getConfiguration().sessionTypes[0]', 'temporary');
+                    testExpected('access.getConfiguration().distinctiveIdentifier', 'not-allowed');
+                    testExpected('access.getConfiguration().persistentState', 'not-allowed');
+                });
+        },
+
+        function() {
+            failingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'unknown/mime; codecs=&quot;unknown&quot;' }] 
+                }],
+                exceptionCode =&gt; {
+                    window.exceptionCode = exceptionCode;
+                    testExpected('exceptionCode.name', 'NotSupportedError');
+                });
+        },
+
+        function() {
+            failingTestWithCapabilities([{
+                    initDataTypes: ['unknownType'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;' }] 
+                }],
+                exceptionCode =&gt; {
+                    window.exceptionCode = exceptionCode;
+                    testExpected('exceptionCode.name', 'NotSupportedError');
+                });
+        },
+
+        function() {
+            run('mock.supportedRobustness = [&quot;high&quot;]');
+            passingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;', robustness: &quot;high&quot; }],
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().videoCapabilities.length', '1');
+                    testExpected('access.getConfiguration().videoCapabilities[0].robustness', 'high');
+                });
+        },
+
+        function() {
+            run('mock.supportedRobustness = [&quot;high&quot;]');
+            failingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;', robustness: &quot;low&quot; }],
+                }],
+                exceptionCode =&gt; {
+                    window.exceptionCode = exceptionCode;
+                    testExpected('exceptionCode.name', 'NotSupportedError');
+                });
+        },
+
+        function() {
+            run('mock.distinctiveIdentifierRequirement = &quot;not-allowed&quot;');
+            passingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    distinctiveIdentifier: 'optional'
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().distinctiveIdentifier', 'not-allowed');
+                });
+        },
+
+        function() {
+            run('mock.distinctiveIdentifiersRequirement = &quot;required&quot;');
+            passingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    distinctiveIdentifier: 'optional'
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().distinctiveIdentifier', 'required');
+                });
+        },
+
+        function() {
+            run('mock.distinctiveIdentifiersRequirement = &quot;not-allowed&quot;');
+            failingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    distinctiveIdentifier: 'required'
+                }],
+                exceptionCode =&gt; {
+                    window.exceptionCode = exceptionCode;
+                    testExpected('exceptionCode.name', 'NotSupportedError');
+                });
+        },
+
+        function() {
+            run('mock.distinctiveIdentifiersRequirement = &quot;not-allowed&quot;');
+            passingTestWithCapabilities([{
+                    label: 'distinctive-identifiers-required',
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    distinctiveIdentifier: 'required'
+                }, {
+                    label: 'distinctive-identifiers-not-required',
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    distinctiveIdentifier: 'optional'
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().label', 'distinctive-identifiers-not-required');
+                    testExpected('access.getConfiguration().distinctiveIdentifier', 'not-allowed');
+                });
+        },
+
+        function() {
+            run('mock.persistentStateRequirement = &quot;required&quot;');
+            passingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    persistentState: 'optional'
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().persistentState', 'required');
+                });
+        },
+
+        function() {
+            run('mock.persistentStateRequirement = &quot;not-allowed&quot;');
+            passingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    persistentState: 'optional'
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().persistentState', 'not-allowed');
+                });
+        },
+
+        function() {
+            run('mock.persistentStateRequirement = &quot;not-allowed&quot;');
+            failingTestWithCapabilities([{
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    persistentState: 'required'
+                }],
+                exceptionCode =&gt; {
+                    window.exceptionCode = exceptionCode;
+                    testExpected('exceptionCode.name', 'NotSupportedError');
+                });
+        },
+
+        function() {
+            run('mock.persistentStateRequirement = &quot;not-allowed&quot;');
+            passingTestWithCapabilities([{
+                    label: 'persistent-state-required',
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    persistentState: 'required'
+                }, {
+                    label: 'persistent-state-not-required',
+                    initDataTypes: ['mock'],
+                    videoCapabilities: [{ contentType: 'video/mock; codecs=&quot;mock&quot;'}],
+                    persistentState: 'optional'
+                }],
+                mediaKeySystemAccess =&gt; {
+                    window.access = mediaKeySystemAccess;
+                    testExpected('access.getConfiguration().label', 'persistent-state-not-required');
+                    testExpected('access.getConfiguration().persistentState', 'not-allowed');
+                });
+        },
+    ];
+    &lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;doTest()&quot;&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -2759,3 +2759,5 @@
</span><span class="cx"> 
</span><span class="cx"> fast/css/deferred-parsing/hover-test.html [ Skip ]
</span><span class="cx"> 
</span><ins>+# New Encrypted Media API not enabled on iOS
+media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html [ Skip ]
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/TestExpectations (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/TestExpectations        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/LayoutTests/platform/mac/TestExpectations        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1467,3 +1467,6 @@
</span><span class="cx"> webkit.org/b/165530 compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html [ Failure ]
</span><span class="cx"> 
</span><span class="cx"> webkit.org/b/165874 [ Debug ] streams/pipe-to.html [ Pass Failure ]
</span><ins>+
+# New Encrypted Media API not enabled on Mac
+media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html [ Skip ]
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1164,7 +1164,6 @@
</span><span class="cx">     bindings/js/JSLocationCustom.cpp
</span><span class="cx">     bindings/js/JSMainThreadExecState.cpp
</span><span class="cx">     bindings/js/JSMediaKeySessionCustom.cpp
</span><del>-    bindings/js/JSMediaKeySystemAccessCustom.cpp
</del><span class="cx">     bindings/js/JSMessageChannelCustom.cpp
</span><span class="cx">     bindings/js/JSMessageEventCustom.cpp
</span><span class="cx">     bindings/js/JSMessagePortCustom.cpp
</span><span class="lines">@@ -3041,6 +3040,7 @@
</span><span class="cx"> 
</span><span class="cx"> if (ENABLE_ENCRYPTED_MEDIA)
</span><span class="cx">     list(APPEND WebCore_SOURCES
</span><ins>+        Modules/encryptedmedia/CDM.cpp
</ins><span class="cx">         Modules/encryptedmedia/MediaKeyMessageEvent.cpp
</span><span class="cx">         Modules/encryptedmedia/MediaKeySession.cpp
</span><span class="cx">         Modules/encryptedmedia/MediaKeyStatusMap.cpp
</span><span class="lines">@@ -3055,11 +3055,13 @@
</span><span class="cx">     list(APPEND WebCore_IDL_FILES
</span><span class="cx">         Modules/encryptedmedia/MediaKeyMessageEvent.idl
</span><span class="cx">         Modules/encryptedmedia/MediaKeySession.idl
</span><ins>+        Modules/encryptedmedia/MediaKeySessionType.idl
</ins><span class="cx">         Modules/encryptedmedia/MediaKeyStatusMap.idl
</span><span class="cx">         Modules/encryptedmedia/MediaKeySystemAccess.idl
</span><span class="cx">         Modules/encryptedmedia/MediaKeySystemConfiguration.idl
</span><span class="cx">         Modules/encryptedmedia/MediaKeySystemMediaCapability.idl
</span><span class="cx">         Modules/encryptedmedia/MediaKeys.idl
</span><ins>+        Modules/encryptedmedia/MediaKeysRequirement.idl
</ins><span class="cx">         Modules/encryptedmedia/NavigatorEME.idl
</span><span class="cx"> 
</span><span class="cx">         html/MediaEncryptedEvent.idl
</span><span class="lines">@@ -3453,6 +3455,7 @@
</span><span class="cx">     testing/Internals.idl
</span><span class="cx">     testing/MallocStatistics.idl
</span><span class="cx">     testing/MemoryInfo.idl
</span><ins>+    testing/MockCDMFactory.idl
</ins><span class="cx">     testing/MockContentFilterSettings.idl
</span><span class="cx">     testing/MockPageOverlay.idl
</span><span class="cx">     testing/TypeConversions.idl
</span><span class="lines">@@ -3469,6 +3472,7 @@
</span><span class="cx">     testing/GCObservation.cpp
</span><span class="cx">     testing/InternalSettings.cpp
</span><span class="cx">     testing/Internals.cpp
</span><ins>+    testing/MockCDMFactory.cpp
</ins><span class="cx">     testing/MockGamepad.cpp
</span><span class="cx">     testing/MockGamepadProvider.cpp
</span><span class="cx">     testing/MockPageOverlay.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/ChangeLog        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1,3 +1,111 @@
</span><ins>+2016-12-17  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Add implementation for navigator.requestMediaKeySystemAccess()
+        https://bugs.webkit.org/show_bug.cgi?id=165850
+
+        Reviewed by Eric Carlson.
+
+        Test: media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html
+
+        Add an implementation of NavigatorEME::requestMediaKeySystemAccess() as well as the CDM
+        object on which it depends.
+
+        * Modules/encryptedmedia/CDM.cpp: Added.
+        (WebCore::cdmFactories):
+        (WebCore::createCDMPrivateForKeySystem):
+        (WebCore::CDM::registerCDMFactory):
+        (WebCore::CDM::unregisterCDMFactory):
+        (WebCore::CDM::supportsKeySystem):
+        (WebCore::CDM::create):
+        (WebCore::CDM::CDM):
+        (WebCore::CDM::getSupportedConfiguration):
+        (WebCore::CDM::doSupportedConfigurationStep):
+        (WebCore::CDM::isPersistentType):
+        (WebCore::CDM::getSupportedCapabilitiesForAudioVideoType):
+        (WebCore::CDM::getConsentStatus):
+        * Modules/encryptedmedia/CDM.h: Added.
+        (WebCore::CDMFactory::~CDMFactory):
+        (WebCore::CDM::keySystem):
+        (WebCore::CDM::createWeakPtr):
+        * Modules/encryptedmedia/CDMPrivate.h: Added.
+        (WebCore::CDMPrivate::~CDMPrivate):
+        * Modules/encryptedmedia/NavigatorEME.cpp:
+        (WebCore::NavigatorEME::requestMediaKeySystemAccess):
+        (WebCore::tryNextSupportedConfiguration):
+        * Modules/encryptedmedia/NavigatorEME.h:
+        * Modules/encryptedmedia/NavigatorEME.idl:
+
+        To aid in testing, a new Internals object is added, MockCDMFactory, which can be
+        controlled by LayoutTests to change the behavior of the Mock objects it creates.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::registerMockCDM):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        * testing/MockCDMFactory.cpp: Added.
+        (WebCore::MockCDMFactory::MockCDMFactory):
+        (WebCore::MockCDMFactory::~MockCDMFactory):
+        (WebCore::MockCDMFactory::unregister):
+        (WebCore::MockCDMFactory::supportsKeySystem):
+        (WebCore::MockCDMFactory::createCDM):
+        (WebCore::MockCDM::MockCDM):
+        (WebCore::MockCDM::supportsInitDataType):
+        (WebCore::MockCDM::supportsConfiguration):
+        (WebCore::MockCDM::supportsConfigurationWithRestrictions):
+        (WebCore::MockCDM::supportsSessionTypeWithConfiguration):
+        (WebCore::MockCDM::supportsRobustness):
+        (WebCore::MockCDM::distinctiveIdentifiersRequirement):
+        (WebCore::MockCDM::persistentStateRequirement):
+        (WebCore::MockCDM::distinctiveIdentifiersAreUniquePerOriginAndClearable):
+        * testing/MockCDMFactory.h: Added.
+        (WebCore::MockCDMFactory::create):
+        (WebCore::MockCDMFactory::supportedDataTypes):
+        (WebCore::MockCDMFactory::setSupportedDataTypes):
+        (WebCore::MockCDMFactory::supportedRobustness):
+        (WebCore::MockCDMFactory::setSupportedRobustness):
+        (WebCore::MockCDMFactory::distinctiveIdentifiersRequirement):
+        (WebCore::MockCDMFactory::setDistinctiveIdentifiersRequirement):
+        (WebCore::MockCDMFactory::persistentStateRequirement):
+        (WebCore::MockCDMFactory::setPersistentStateRequirement):
+        * testing/MockCDMFactory.idl: Added.
+
+        Move the MediaKeySessionType definition out of the MediaKeys.idl file and into its own.
+        Move the MediaKeysRequiriment definition out of the MediaKeySystemConfiguration.idl file
+        and into its own. Generally fix up the .idl files so that they properly work with their
+        implementation files.
+
+        * Modules/encryptedmedia/MediaKeySessionType.idl: Added.
+        * Modules/encryptedmedia/MediaKeySystemAccess.cpp:
+        (WebCore::MediaKeySystemAccess::create):
+        (WebCore::MediaKeySystemAccess::MediaKeySystemAccess):
+        (WebCore::MediaKeySystemAccess::keySystem): Deleted.
+        (WebCore::MediaKeySystemAccess::getConfiguration): Deleted.
+        * Modules/encryptedmedia/MediaKeySystemAccess.h:
+        (WebCore::MediaKeySystemAccess::keySystem):
+        (WebCore::MediaKeySystemAccess::getConfiguration):
+        (WebCore::MediaKeySystemAccess::create): Deleted.
+        * Modules/encryptedmedia/MediaKeySystemAccess.idl:
+        * Modules/encryptedmedia/MediaKeySystemConfiguration.h:
+        * Modules/encryptedmedia/MediaKeySystemConfiguration.idl:
+        * Modules/encryptedmedia/MediaKeySystemMediaCapability.idl:
+        * Modules/encryptedmedia/MediaKeys.idl:
+        * Modules/encryptedmedia/MediaKeysRequirement.idl: Added.
+        * Modules/encryptedmedia/MediaKeysRestrictions.h: Added.
+        * bindings/js/JSMediaKeySystemAccessCustom.cpp: Removed.
+
+        As some of these enums are referenced in the Internals project, they need to be exported
+        from WebCore correctly. Teach the code generator how to export the symbols generated by
+        enums.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateEnumerationHeaderContent):
+
+        Add new files to the project.
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * WebCore.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2016-12-17  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove WebCore::Dictionary, which is now unused
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.make        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/DerivedSources.make        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -94,11 +94,13 @@
</span><span class="cx">     $(WebCore)/Modules/applepay/ApplePayValidateMerchantEvent.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeyMessageEvent.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeySession.idl \
</span><ins>+    $(WebCore)/Modules/encryptedmedia/MediaKeySessionType.idl \
</ins><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeyStatusMap.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeySystemAccess.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeySystemConfiguration.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeys.idl \
</span><ins>+    $(WebCore)/Modules/encryptedmedia/MediaKeysRequirement.idl \
</ins><span class="cx">     $(WebCore)/Modules/encryptedmedia/NavigatorEME.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/legacy/WebKitMediaKeyMessageEvent.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/legacy/WebKitMediaKeyNeededEvent.idl \
</span><span class="lines">@@ -748,6 +750,7 @@
</span><span class="cx">     $(WebCore)/testing/Internals.idl \
</span><span class="cx">     $(WebCore)/testing/MallocStatistics.idl \
</span><span class="cx">     $(WebCore)/testing/MemoryInfo.idl \
</span><ins>+    $(WebCore)/testing/MockCDMFactory.idl \
</ins><span class="cx">     $(WebCore)/testing/MockContentFilterSettings.idl \
</span><span class="cx">     $(WebCore)/testing/MockPageOverlay.idl \
</span><span class="cx">     $(WebCore)/testing/TypeConversions.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,616 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;CDM.h&quot;
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include &quot;CDMPrivate.h&quot;
+#include &quot;Document.h&quot;
+#include &quot;MediaKeysRestrictions.h&quot;
+#include &quot;MediaPlayer.h&quot;
+#include &quot;NotImplemented.h&quot;
+#include &quot;ParsedContentType.h&quot;
+#include &quot;ScriptExecutionContext.h&quot;
+#include &quot;SecurityOrigin.h&quot;
+#include &lt;wtf/NeverDestroyed.h&gt;
+
+namespace WebCore {
+
+static Vector&lt;CDMFactory*&gt;&amp; cdmFactories()
+{
+    static NeverDestroyed&lt;Vector&lt;CDMFactory*&gt;&gt; factories;
+    return factories;
+}
+
+static std::unique_ptr&lt;CDMPrivate&gt; createCDMPrivateForKeySystem(const String&amp; keySystem, CDM&amp; cdm)
+{
+    for (auto* factory : cdmFactories()) {
+        if (factory-&gt;supportsKeySystem(keySystem))
+            return factory-&gt;createCDM(cdm);
+    }
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+void CDM::registerCDMFactory(CDMFactory&amp; factory)
+{
+    ASSERT(!cdmFactories().contains(&amp;factory));
+    cdmFactories().append(&amp;factory);
+}
+
+void CDM::unregisterCDMFactory(CDMFactory&amp; factory)
+{
+    ASSERT(cdmFactories().contains(&amp;factory));
+    cdmFactories().removeAll(&amp;factory);
+}
+
+bool CDM::supportsKeySystem(const String&amp; keySystem)
+{
+    for (auto* factory : cdmFactories()) {
+        if (factory-&gt;supportsKeySystem(keySystem))
+            return true;
+    }
+    return false;
+}
+
+Ref&lt;CDM&gt; CDM::create(Document&amp; document, const String&amp; keySystem)
+{
+    return adoptRef(*new CDM(document, keySystem));
+}
+
+CDM::CDM(Document&amp; document, const String&amp; keySystem)
+    : ContextDestructionObserver(&amp;document)
+    , m_keySystem(keySystem)
+    , m_private(createCDMPrivateForKeySystem(keySystem, *this))
+    , m_weakPtrFactory(this)
+{
+    ASSERT(supportsKeySystem(keySystem));
+    for (auto* factory : cdmFactories()) {
+        if (!factory-&gt;supportsKeySystem(keySystem))
+            continue;
+        m_private = factory-&gt;createCDM(*this);
+    }
+}
+
+CDM::~CDM() = default;
+
+void CDM::getSupportedConfiguration(MediaKeySystemConfiguration&amp;&amp; candidateConfiguration, SupportedConfigurationCallback&amp;&amp; callback)
+{
+    // https://w3c.github.io/encrypted-media/#get-supported-configuration
+    // W3C Editor's Draft 09 November 2016
+
+    // 3.1.1.1 Get Supported Configuration
+    // Given a Key Systems implementation implementation, MediaKeySystemConfiguration candidate configuration, and origin,
+    // this algorithm returns a supported configuration or NotSupported as appropriate.
+
+    // 1. Let supported configuration be ConsentDenied.
+    // 2. Initialize restrictions to indicate that no configurations have had user consent denied.
+    MediaKeysRestrictions restrictions { };
+    doSupportedConfigurationStep(WTFMove(candidateConfiguration), WTFMove(restrictions), WTFMove(callback));
+}
+
+void CDM::doSupportedConfigurationStep(MediaKeySystemConfiguration&amp;&amp; candidateConfiguration, MediaKeysRestrictions&amp;&amp; restrictions, SupportedConfigurationCallback&amp;&amp; callback)
+{
+    // https://w3c.github.io/encrypted-media/#get-supported-configuration
+    // W3C Editor's Draft 09 November 2016, ctd.
+
+    // 3.1.1.1 Get Supported Configuration
+    // 3. Repeat the following step while supported configuration is ConsentDenied:
+    // 3.1. Let supported configuration and, if provided, restrictions be the result of executing the
+    // Get Supported Configuration and Consent algorithm with implementation, candidate configuration,
+    // restrictions and origin.
+    auto optionalConfiguration = getSupportedConfiguration(candidateConfiguration, restrictions);
+    if (!optionalConfiguration) {
+        callback(std::nullopt);
+        return;
+    }
+
+    auto consentCallback = [weakThis = createWeakPtr(), callback = WTFMove(callback)] (ConsentStatus status, MediaKeySystemConfiguration&amp;&amp; configuration, MediaKeysRestrictions&amp;&amp; restrictions) mutable {
+        if (!weakThis) {
+            callback(std::nullopt);
+            return;
+        }
+        // 3.1.1.2 Get Supported Configuration and Consent, ctd.
+        // 22. Let consent status and updated restrictions be the result of running the Get Consent Status algorithm on accumulated configuration,
+        //     restrictions and origin and follow the steps for the value of consent status from the following list:
+        switch (status) {
+        case ConsentStatus::ConsentDenied:
+            // â†³ ConsentDenied:
+            //    Return ConsentDenied and updated restrictions.
+            weakThis-&gt;doSupportedConfigurationStep(WTFMove(configuration), WTFMove(restrictions), WTFMove(callback));
+            return;
+
+        case ConsentStatus::InformUser:
+            // â†³ InformUser
+            //    Inform the user that accumulated configuration is in use in the origin including, specifically, the information that
+            //    Distinctive Identifier(s) and/or Distinctive Permanent Identifier(s) as appropriate will be used if the
+            //    distinctiveIdentifier member of accumulated configuration is &quot;required&quot;. Continue to the next step.
+            // NOTE: Implement.
+            break;
+
+        case ConsentStatus::Allowed:
+            // â†³ Allowed:
+            // Continue to the next step.
+            break;
+        }
+        // 23. Return accumulated configuration.
+        callback(WTFMove(configuration));
+    };
+    getConsentStatus(WTFMove(optionalConfiguration.value()), WTFMove(restrictions), consentCallback);
+}
+
+bool CDM::isPersistentType(MediaKeySessionType sessionType)
+{
+    // https://w3c.github.io/encrypted-media/#is-persistent-session-type
+    // W3C Editor's Draft 09 November 2016
+
+    // 5.1.1. Is persistent session type?
+    // 1. Let the session type be the specified MediaKeySessionType value.
+    // 2. Follow the steps for the value of session type from the following list:
+    switch (sessionType) {
+    case MediaKeySessionType::Temporary:
+        // â†³ &quot;temporary&quot;
+        return false;
+    case MediaKeySessionType::PersistentLicense:
+    case MediaKeySessionType::PersistentUsageRecord:
+        // â†³ &quot;persistent-license&quot;
+        return true;
+    }
+}
+
+std::optional&lt;MediaKeySystemConfiguration&gt; CDM::getSupportedConfiguration(const MediaKeySystemConfiguration&amp; candidateConfiguration, MediaKeysRestrictions&amp; restrictions)
+{
+    // https://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
+    // W3C Editor's Draft 09 November 2016
+
+    ASSERT(m_private);
+    if (!m_private)
+        return std::nullopt;
+
+    // 3.1.1.2 Get Supported Configuration and Consent
+    // Given a Key Systems implementation implementation, MediaKeySystemConfiguration candidate configuration,
+    // restrictions and origin, this algorithm returns a supported configuration, NotSupported, or ConsentDenied
+    // as appropriate and, in the ConsentDenied case, restrictions.
+
+    // 1. Let accumulated configuration be a new MediaKeySystemConfiguration dictionary.
+    MediaKeySystemConfiguration accumulatedConfiguration { };
+
+    // 2. Set the label member of accumulated configuration to equal the label member of candidate configuration.
+    accumulatedConfiguration.label = candidateConfiguration.label;
+
+    // 3. If the initDataTypes member of candidate configuration is non-empty, run the following steps:
+    if (!candidateConfiguration.initDataTypes.isEmpty()) {
+        // 3.1. Let supported types be an empty sequence of DOMStrings.
+        Vector&lt;String&gt; supportedTypes;
+
+        // 3.2. For each value in candidate configuration's initDataTypes member:
+        for (auto initDataType : candidateConfiguration.initDataTypes) {
+            // 3.2.1. Let initDataType be the value.
+            // 3.2.2. If the implementation supports generating requests based on initDataType, add initDataType
+            //        to supported types. String comparison is case-sensitive. The empty string is never supported.
+            if (initDataType.isEmpty())
+                continue;
+
+            if (m_private &amp;&amp; m_private-&gt;supportsInitDataType(initDataType))
+                supportedTypes.append(initDataType);
+        }
+
+        // 3.3. If supported types is empty, return NotSupported.
+        if (supportedTypes.isEmpty())
+            return std::nullopt;
+
+        // 3.4. Set the initDataTypes member of accumulated configuration to supported types.
+        accumulatedConfiguration.initDataTypes = WTFMove(supportedTypes);
+    }
+
+    // 4. Let distinctive identifier requirement be the value of candidate configuration's distinctiveIdentifier member.
+    MediaKeysRequirement distinctiveIdentifierRequirement = candidateConfiguration.distinctiveIdentifier;
+
+    // 5. If distinctive identifier requirement is &quot;optional&quot; and Distinctive Identifiers are not allowed according to
+    //    restrictions, set distinctive identifier requirement to &quot;not-allowed&quot;.
+    if (distinctiveIdentifierRequirement == MediaKeysRequirement::Optional &amp;&amp; restrictions.distinctiveIdentifierDenied)
+        distinctiveIdentifierRequirement = MediaKeysRequirement::NotAllowed;
+
+    // 6. Follow the steps for distinctive identifier requirement from the following list:
+    switch (distinctiveIdentifierRequirement) {
+    case MediaKeysRequirement::Required:
+        // â†³ &quot;required&quot;
+        // If the implementation does not support use of Distinctive Identifier(s) in combination
+        // with accumulated configuration and restrictions, return NotSupported.
+        if (m_private-&gt;distinctiveIdentifiersRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::NotAllowed)
+            return std::nullopt;
+        break;
+
+    case MediaKeysRequirement::Optional:
+        // â†³ &quot;optional&quot;
+        // Continue with the following steps.
+        break;
+
+    case MediaKeysRequirement::NotAllowed:
+        // â†³ &quot;not-allowed&quot;
+        // If the implementation requires use Distinctive Identifier(s) or Distinctive Permanent Identifier(s)
+        // in combination with accumulated configuration and restrictions, return NotSupported.
+        if (m_private-&gt;distinctiveIdentifiersRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required)
+            return std::nullopt;
+        break;
+    }
+
+    // 7. Set the distinctiveIdentifier member of accumulated configuration to equal distinctive identifier requirement.
+    accumulatedConfiguration.distinctiveIdentifier = distinctiveIdentifierRequirement;
+
+    // 8. Let persistent state requirement be equal to the value of candidate configuration's persistentState member.
+    MediaKeysRequirement persistentStateRequirement = candidateConfiguration.persistentState;
+
+    // 9. If persistent state requirement is &quot;optional&quot; and persisting state is not allowed according to restrictions,
+    //    set persistent state requirement to &quot;not-allowed&quot;.
+    if (persistentStateRequirement == MediaKeysRequirement::Optional &amp;&amp; restrictions.persistentStateDenied)
+        persistentStateRequirement =  MediaKeysRequirement::NotAllowed;
+
+    // 10. Follow the steps for persistent state requirement from the following list:
+    switch (persistentStateRequirement) {
+    case MediaKeysRequirement::Required:
+        // â†³ &quot;required&quot;
+        // If the implementation does not support persisting state in combination with accumulated configuration
+        // and restrictions, return NotSupported.
+        if (m_private-&gt;persistentStateRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::NotAllowed)
+            return std::nullopt;
+        break;
+
+    case MediaKeysRequirement::Optional:
+        // â†³ &quot;optional&quot;
+        // Continue with the following steps.
+        break;
+
+    case MediaKeysRequirement::NotAllowed:
+        // â†³ &quot;not-allowed&quot;
+        // If the implementation requires persisting state in combination with accumulated configuration
+        // and restrictions, return NotSupported
+        if (m_private-&gt;persistentStateRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required)
+            return std::nullopt;
+        break;
+    }
+
+    // 11. Set the persistentState member of accumulated configuration to equal the value of persistent state requirement.
+    accumulatedConfiguration.persistentState = persistentStateRequirement;
+
+    // 12. Follow the steps for the first matching condition from the following list:
+    Vector&lt;MediaKeySessionType&gt; sessionTypes;
+
+    if (!candidateConfiguration.sessionTypes.isEmpty()) {
+        // â†³ If the sessionTypes member is present [WebIDL] in candidate configuration
+        // Let session types be candidate configuration's sessionTypes member.
+        sessionTypes = candidateConfiguration.sessionTypes;
+    } else {
+        // â†³ Otherwise
+        // Let session types be [ &quot;temporary&quot; ].
+        sessionTypes = { MediaKeySessionType::Temporary };
+    }
+
+    // 13. For each value in session types:
+    for (auto&amp; sessionType : sessionTypes) {
+        // 13.1. Let session type be the value.
+        // 13.2. If accumulated configuration's persistentState value is &quot;not-allowed&quot; and the
+        //       Is persistent session type? algorithm returns true for session type return NotSupported.
+        if (accumulatedConfiguration.persistentState == MediaKeysRequirement::NotAllowed &amp;&amp; isPersistentType(sessionType))
+            return std::nullopt;
+
+        // 13.3. If the implementation does not support session type in combination with accumulated configuration
+        //       and restrictions for other reasons, return NotSupported.
+        if (!m_private-&gt;supportsSessionTypeWithConfiguration(sessionType, accumulatedConfiguration))
+            return std::nullopt;
+
+        // 13.4 If accumulated configuration's persistentState value is &quot;optional&quot; and the result of running the Is
+        //      persistent session type? algorithm on session type is true, change accumulated configuration's persistentState
+        //      value to &quot;required&quot;.
+        if (accumulatedConfiguration.persistentState == MediaKeysRequirement::Optional &amp;&amp; isPersistentType(sessionType))
+            accumulatedConfiguration.persistentState = MediaKeysRequirement::Required;
+    }
+
+    // 14. Set the sessionTypes member of accumulated configuration to session types.
+    accumulatedConfiguration.sessionTypes = sessionTypes;
+
+    // 15. If the videoCapabilities and audioCapabilities members in candidate configuration are both empty, return NotSupported.
+    if (candidateConfiguration.videoCapabilities.isEmpty() &amp;&amp; candidateConfiguration.audioCapabilities.isEmpty())
+        return std::nullopt;
+
+    // 16. â†³ If the videoCapabilities member in candidate configuration is non-empty:
+    if (!candidateConfiguration.videoCapabilities.isEmpty()) {
+        // 16.1. Let video capabilities be the result of executing the Get Supported Capabilities for Audio/Video Type algorithm on
+        //       Video, candidate configuration's videoCapabilities member, accumulated configuration, and restrictions.
+        auto videoCapabilities = getSupportedCapabilitiesForAudioVideoType(AudioVideoType::Video, candidateConfiguration.videoCapabilities, accumulatedConfiguration, restrictions);
+
+        // 16.2. If video capabilities is null, return NotSupported.
+        if (!videoCapabilities)
+            return std::nullopt;
+
+        // 16.3 Set the videoCapabilities member of accumulated configuration to video capabilities.
+        accumulatedConfiguration.videoCapabilities = WTFMove(videoCapabilities.value());
+    } else {
+        // 16. â†³ Otherwise:
+        //     Set the videoCapabilities member of accumulated configuration to an empty sequence.
+        accumulatedConfiguration.videoCapabilities = { };
+    }
+
+    // 17. â†³ If the audioCapabilities member in candidate configuration is non-empty:
+    if (!candidateConfiguration.audioCapabilities.isEmpty()) {
+        // 17.1. Let audio capabilities be the result of executing the Get Supported Capabilities for Audio/Video Type algorithm on
+        //       Audio, candidate configuration's audioCapabilities member, accumulated configuration, and restrictions.
+        auto audioCapabilities = getSupportedCapabilitiesForAudioVideoType(AudioVideoType::Audio, candidateConfiguration.audioCapabilities, accumulatedConfiguration, restrictions);
+
+        // 17.2. If audio capabilities is null, return NotSupported.
+        if (!audioCapabilities)
+            return std::nullopt;
+
+        // 17.3 Set the audioCapabilities member of accumulated configuration to audio capabilities.
+        accumulatedConfiguration.audioCapabilities = WTFMove(audioCapabilities.value());
+    } else {
+        // 17. â†³ Otherwise:
+        //     Set the audioCapabilities member of accumulated configuration to an empty sequence.
+        accumulatedConfiguration.audioCapabilities = { };
+    }
+
+    // 18. If accumulated configuration's distinctiveIdentifier value is &quot;optional&quot;, follow the steps for the first matching
+    //     condition from the following list:
+    if (accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Optional) {
+        // â†³ If the implementation requires use Distinctive Identifier(s) or Distinctive Permanent Identifier(s) for any of the
+        //    combinations in accumulated configuration
+        if (m_private-&gt;distinctiveIdentifiersRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required) {
+            // Change accumulated configuration's distinctiveIdentifier value to &quot;required&quot;.
+            accumulatedConfiguration.distinctiveIdentifier = MediaKeysRequirement::Required;
+        } else {
+            // â†³ Otherwise
+            //    Change accumulated configuration's distinctiveIdentifier value to &quot;not-allowed&quot;.
+            accumulatedConfiguration.distinctiveIdentifier = MediaKeysRequirement::NotAllowed;
+        }
+    }
+
+    // 19. If accumulated configuration's persistentState value is &quot;optional&quot;, follow the steps for the first matching
+    //     condition from the following list:
+    if (accumulatedConfiguration.persistentState == MediaKeysRequirement::Optional) {
+        // â†³ If the implementation requires persisting state for any of the combinations in accumulated configuration
+        if (m_private-&gt;persistentStateRequirement(accumulatedConfiguration, restrictions) == MediaKeysRequirement::Required) {
+            // Change accumulated configuration's persistentState value to &quot;required&quot;.
+            accumulatedConfiguration.persistentState = MediaKeysRequirement::Required;
+        } else {
+            // â†³ Otherwise
+            //    Change accumulated configuration's persistentState value to &quot;not-allowed&quot;.
+            accumulatedConfiguration.persistentState = MediaKeysRequirement::NotAllowed;
+        }
+    }
+
+    // 20. If implementation in the configuration specified by the combination of the values in accumulated configuration
+    //     is not supported or not allowed in the origin, return NotSupported.
+    if (!m_private-&gt;supportsConfiguration(accumulatedConfiguration))
+        return std::nullopt;
+
+    Document* document = downcast&lt;Document&gt;(m_scriptExecutionContext);
+    if (!document)
+        return std::nullopt;
+
+    SecurityOrigin* origin = document-&gt;securityOrigin();
+    SecurityOrigin* topOrigin = document-&gt;topOrigin();
+    if (!origin || !topOrigin)
+        return std::nullopt;
+
+    if ((accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Required || accumulatedConfiguration.persistentState == MediaKeysRequirement::Required) &amp;&amp; !origin-&gt;canAccessLocalStorage(topOrigin))
+        return std::nullopt;
+
+    return WTFMove(accumulatedConfiguration);
+    // NOTE: Continued in getConsentStatus().
+}
+
+std::optional&lt;Vector&lt;MediaKeySystemMediaCapability&gt;&gt; CDM::getSupportedCapabilitiesForAudioVideoType(CDM::AudioVideoType type, const Vector&lt;MediaKeySystemMediaCapability&gt;&amp; requestedCapabilities, const MediaKeySystemConfiguration&amp; partialConfiguration, MediaKeysRestrictions&amp; restrictions)
+{
+    // https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
+    // W3C Editor's Draft 09 November 2016
+
+    ASSERT(m_private);
+    if (!m_private)
+        return std::nullopt;
+
+    // 3.1.1.3 Get Supported Capabilities for Audio/Video Type
+
+    // Given an audio/video type, MediaKeySystemMediaCapability sequence requested media capabilities, MediaKeySystemConfiguration
+    // partial configuration, and restrictions, this algorithm returns a sequence of supported MediaKeySystemMediaCapability values
+    // for this audio/video type or null as appropriate.
+
+    // 1. Let local accumulated configuration be a local copy of partial configuration.
+    MediaKeySystemConfiguration accumulatedConfiguration = partialConfiguration;
+
+    // 2. Let supported media capabilities be an empty sequence of MediaKeySystemMediaCapability dictionaries.
+    Vector&lt;MediaKeySystemMediaCapability&gt; supportedMediaCapabilities { };
+
+    // 3. For each requested media capability in requested media capabilities:
+    for (auto&amp; requestedCapability : requestedCapabilities) {
+        // 3.1. Let content type be requested media capability's contentType member.
+        // 3.2. Let robustness be requested media capability's robustness member.
+        String robustness = requestedCapability.robustness;
+
+        // 3.3. If content type is the empty string, return null.
+        if (requestedCapability.contentType.isEmpty())
+            return std::nullopt;
+
+        // 3.4. If content type is an invalid or unrecognized MIME type, continue to the next iteration.
+        if (!isValidContentType(requestedCapability.contentType))
+            continue;
+
+        // 3.5. Let container be the container type specified by content type.
+        ParsedContentType contentType { requestedCapability.contentType };
+        String container = contentType.mimeType();
+
+        // 3.6. If the user agent does not support container, continue to the next iteration. The case-sensitivity
+        //      of string comparisons is determined by the appropriate RFC.
+        // 3.7. Let parameters be the RFC 6381 [RFC6381] parameters, if any, specified by content type.
+        // 3.8. If the user agent does not recognize one or more parameters, continue to the next iteration.
+        // 3.9. Let media types be the set of codecs and codec constraints specified by parameters. The case-sensitivity
+        //      of string comparisons is determined by the appropriate RFC or other specification.
+        String codecs = contentType.parameterValueForName(&quot;codecs&quot;);
+        if (contentType.parameterCount() &gt; (codecs.isEmpty() ? 0 : 1))
+            continue;
+
+        // 3.10. If media types is empty:
+        if (codecs.isEmpty()) {
+            // â†³ If container normatively implies a specific set of codecs and codec constraints:
+            // â†³ Otherwise:
+            notImplemented();
+        }
+
+        // 3.11. If content type is not strictly a audio/video type, continue to the next iteration.
+        // 3.12. If robustness is not the empty string and contains an unrecognized value or a value not supported by
+        //       implementation, continue to the next iteration. String comparison is case-sensitive.
+        if (!robustness.isEmpty() &amp;&amp; !m_private-&gt;supportsRobustness(robustness))
+            continue;
+
+        // 3.13. If the user agent and implementation definitely support playback of encrypted media data for the
+        //       combination of container, media types, robustness and local accumulated configuration in combination
+        //       with restrictions:
+        MediaEngineSupportParameters parameters;
+        parameters.type = contentType.mimeType();
+        parameters.codecs = codecs;
+        if (!MediaPlayer::supportsType(parameters, nullptr)) {
+            // Try with Media Source:
+            parameters.isMediaSource = true;
+            if (!MediaPlayer::supportsType(parameters, nullptr))
+                continue;
+        }
+
+        if (!m_private-&gt;supportsConfigurationWithRestrictions(accumulatedConfiguration, restrictions))
+            continue;
+
+        // 3.13.1. Add requested media capability to supported media capabilities.
+        supportedMediaCapabilities.append(requestedCapability);
+
+        // 3.13.2. â†³ If audio/video type is Video:
+        //         Add requested media capability to the videoCapabilities member of local accumulated configuration.
+        if (type == AudioVideoType::Video)
+            accumulatedConfiguration.videoCapabilities.append(requestedCapability);
+        // 3.13.2. â†³ If audio/video type is Audio:
+        //         Add requested media capability to the audioCapabilities member of local accumulated configuration.
+        else
+            accumulatedConfiguration.audioCapabilities.append(requestedCapability);
+    }
+
+    // 4. If supported media capabilities is empty, return null.
+    if (supportedMediaCapabilities.isEmpty())
+        return std::nullopt;
+
+    // 5. Return supported media capabilities.
+    return supportedMediaCapabilities;
+}
+
+void CDM::getConsentStatus(MediaKeySystemConfiguration&amp;&amp; accumulatedConfiguration, MediaKeysRestrictions&amp;&amp; restrictions, ConsentStatusCallback&amp;&amp; callback)
+{
+    // https://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
+    // W3C Editor's Draft 09 November 2016
+    if (!m_scriptExecutionContext) {
+        callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+        return;
+    }
+
+    // NOTE: In the future, these checks belowe will involve asking the page client, possibly across a process boundary.
+    // They will by necessity be asynchronous with callbacks. For now, imply this behavior by performing it in an async task.
+
+    m_scriptExecutionContext-&gt;postTask([this, weakThis = createWeakPtr(), accumulatedConfiguration = WTFMove(accumulatedConfiguration), restrictions = WTFMove(restrictions), callback = WTFMove(callback)] (ScriptExecutionContext&amp;) mutable {
+        if (!weakThis || !m_private) {
+            callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+            return;
+        }
+
+        Document* document = downcast&lt;Document&gt;(m_scriptExecutionContext);
+        if (!document) {
+            callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+            return;
+        }
+
+        SecurityOrigin* origin = document-&gt;securityOrigin();
+        SecurityOrigin* topOrigin = document-&gt;topOrigin();
+        if (!origin || !topOrigin) {
+            callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+            return;
+        }
+
+        // 3.1.1.2 Get Supported Configuration and Consent, ctd.
+        // 21. If accumulated configuration's distinctiveIdentifier value is &quot;required&quot; and the Distinctive Identifier(s) associated
+        //     with accumulated configuration are not unique per origin and profile and clearable:
+        if (accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Required &amp;&amp; !m_private-&gt;distinctiveIdentifiersAreUniquePerOriginAndClearable(accumulatedConfiguration)) {
+            // 21.1. Update restrictions to reflect that all configurations described by accumulated configuration do not have user consent.
+            restrictions.distinctiveIdentifierDenied = true;
+            callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+            return;
+        }
+
+        // https://w3c.github.io/encrypted-media/#get-consent-status
+        // 3.1.1.4 Get Consent Status
+        // Given an accumulated configuration, restrictions and origin, this algorithm returns the consent status for accumulated
+        // configuration and origin as one of ConsentDenied, InformUser or Allowed, together with an updated value for restrictions
+        // in the ConsentDenied case.
+
+        // 1. If there is persisted denial for origin indicating that accumulated configuration is not allowed, run the following steps:
+        // 1.1. Update restrictions to reflect the configurations for which consent has been denied.
+        // 1.2. Return ConsentDenied and restrictions.
+        // 2. If there is persisted consent for origin indicating accumulated configuration is allowed, return Allowed.
+        // NOTE: persisted denial / consent unimplemented.
+
+        // 3. If any of the following are true:
+        //    â†³ The distinctiveIdentifier member of accumulated configuration is not &quot;not-allowed&quot; and the combination of the User Agent,
+        //       implementation and accumulated configuration does not follow all the recommendations of Allow Persistent Data to Be Cleared
+        //       with respect to Distinctive Identifier(s).
+        // NOTE: assume that implementations follow all recommendations.
+
+        //    â†³ The user agent requires explicit user consent for the accumulated configuration for other reasons.
+        // NOTE: assume the user agent does not require explicit user consent.
+
+        // 3.1. Request user consent to use accumulated configuration in the origin and wait for the user response.
+        //      The consent must include consent to use a Distinctive Identifier(s) and/or Distinctive Permanent Identifier(s) as appropriate
+        //      if accumulated configuration's distinctiveIdentifier member is &quot;required&quot;.
+        // 3.2. If consent was denied, run the following steps:
+        // 3.2.1. Update restrictions to reflect the configurations for which consent was denied.
+        // 3.2.1. Return ConsentDenied and restrictions.
+        // NOTE: assume implied consent if the combination of origin and topOrigin allows it.
+        if (accumulatedConfiguration.distinctiveIdentifier == MediaKeysRequirement::Required &amp;&amp; !origin-&gt;canAccessLocalStorage(topOrigin)) {
+            restrictions.distinctiveIdentifierDenied = true;
+            callback(ConsentStatus::ConsentDenied, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+            return;
+        }
+
+        // 4. If the distinctiveIdentifier member of accumulated configuration is not &quot;not-allowed&quot;, return InformUser.
+        if (accumulatedConfiguration.distinctiveIdentifier != MediaKeysRequirement::NotAllowed) {
+            callback(ConsentStatus::InformUser, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+            return;
+        }
+
+        // 5. If the user agent requires informing the user for the accumulated configuration for other reasons, return InformUser.
+        // NOTE: assume the user agent does not require informing the user.
+
+        // 6. Return Allowed.
+        callback(ConsentStatus::Allowed, WTFMove(accumulatedConfiguration), WTFMove(restrictions));
+    });
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/encryptedmedia/CDM.h (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,106 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include &quot;ContextDestructionObserver.h&quot;
+#include &quot;MediaKeySystemConfiguration.h&quot;
+#include &lt;functional&gt;
+#include &lt;wtf/HashSet.h&gt;
+#include &lt;wtf/Ref.h&gt;
+#include &lt;wtf/RefCounted.h&gt;
+#include &lt;wtf/WeakPtr.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+class CDM;
+class CDMPrivate;
+class Document;
+class ScriptExecutionContext;
+
+struct MediaKeysRestrictions;
+
+class CDMFactory {
+public:
+    virtual ~CDMFactory() { };
+    virtual std::unique_ptr&lt;CDMPrivate&gt; createCDM(CDM&amp;) = 0;
+    virtual bool supportsKeySystem(const String&amp;) = 0;
+};
+
+class CDM : public RefCounted&lt;CDM&gt;, private ContextDestructionObserver {
+public:
+    WEBCORE_EXPORT static void registerCDMFactory(CDMFactory&amp;);
+    WEBCORE_EXPORT static void unregisterCDMFactory(CDMFactory&amp;);
+
+    static bool supportsKeySystem(const String&amp;);
+    static bool isPersistentType(MediaKeySessionType);
+
+    static Ref&lt;CDM&gt; create(Document&amp;, const String&amp; keySystem);
+    ~CDM();
+
+    using SupportedConfigurationCallback = std::function&lt;void(std::optional&lt;MediaKeySystemConfiguration&gt;)&gt;;
+    void getSupportedConfiguration(MediaKeySystemConfiguration&amp;&amp; candidateConfiguration, SupportedConfigurationCallback&amp;&amp;);
+
+    const String&amp; keySystem() const { return m_keySystem; }
+
+private:
+    CDM(Document&amp;, const String&amp; keySystem);
+
+    enum class ConfigurationStatus {
+        Supported,
+        NotSupported,
+        ConsentDenied,
+    };
+
+    enum class ConsentStatus {
+        ConsentDenied,
+        InformUser,
+        Allowed,
+    };
+
+    enum class AudioVideoType {
+        Audio,
+        Video,
+    };
+
+    void doSupportedConfigurationStep(MediaKeySystemConfiguration&amp;&amp; candidateConfiguration, MediaKeysRestrictions&amp;&amp;, SupportedConfigurationCallback&amp;&amp;);
+    std::optional&lt;MediaKeySystemConfiguration&gt;  getSupportedConfiguration(const MediaKeySystemConfiguration&amp; candidateConfiguration, MediaKeysRestrictions&amp;);
+    std::optional&lt;Vector&lt;MediaKeySystemMediaCapability&gt;&gt; getSupportedCapabilitiesForAudioVideoType(AudioVideoType, const Vector&lt;MediaKeySystemMediaCapability&gt;&amp; requestedCapabilities, const MediaKeySystemConfiguration&amp; partialConfiguration, MediaKeysRestrictions&amp;);
+
+    WeakPtr&lt;CDM&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
+    using ConsentStatusCallback = std::function&lt;void(ConsentStatus, MediaKeySystemConfiguration&amp;&amp;, MediaKeysRestrictions&amp;&amp;)&gt;;
+    void getConsentStatus(MediaKeySystemConfiguration&amp;&amp; accumulatedConfiguration, MediaKeysRestrictions&amp;&amp;, ConsentStatusCallback&amp;&amp;);
+    String m_keySystem;
+    std::unique_ptr&lt;CDMPrivate&gt; m_private;
+    WeakPtrFactory&lt;CDM&gt; m_weakPtrFactory;
+};
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMPrivateh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include &quot;MediaKeySessionType.h&quot;
+#include &quot;MediaKeysRequirement.h&quot;
+#include &lt;wtf/Forward.h&gt;
+
+namespace WebCore {
+
+struct MediaKeySystemConfiguration;
+struct MediaKeysRestrictions;
+
+class CDMPrivate {
+public:
+    virtual ~CDMPrivate() { }
+    virtual bool supportsInitDataType(const String&amp;) = 0;
+    virtual bool supportsConfiguration(const MediaKeySystemConfiguration&amp;) = 0;
+    virtual bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;) = 0;
+    virtual bool supportsSessionTypeWithConfiguration(MediaKeySessionType&amp;, const MediaKeySystemConfiguration&amp;) = 0;
+    virtual bool supportsRobustness(const String&amp;) = 0;
+    virtual MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;) = 0;
+    virtual MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;) = 0;
+    virtual bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&amp;) = 0;
+};
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySessionTypeidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySessionType.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=ENCRYPTED_MEDIA,
+    ImplementedAs=MediaKeySessionType
+]
+enum MediaKeySessionType {
+    &quot;temporary&quot;,
+    &quot;persistent-usage-record&quot;,
+    &quot;persistent-license&quot;
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySystemAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -31,27 +31,26 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="cx"> 
</span><ins>+#include &quot;CDM.h&quot;
</ins><span class="cx"> #include &quot;MediaKeySystemConfiguration.h&quot;
</span><span class="cx"> #include &quot;NotImplemented.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-MediaKeySystemAccess::MediaKeySystemAccess() = default;
-
-MediaKeySystemAccess::~MediaKeySystemAccess() = default;
-
-const String&amp; MediaKeySystemAccess::keySystem() const
</del><ins>+Ref&lt;MediaKeySystemAccess&gt; MediaKeySystemAccess::create(const String&amp; keySystem, MediaKeySystemConfiguration&amp;&amp; configuration, Ref&lt;CDM&gt;&amp;&amp; implementation)
</ins><span class="cx"> {
</span><del>-    notImplemented();
-    return m_keySystem;
</del><ins>+    return adoptRef(*new MediaKeySystemAccess(keySystem, WTFMove(configuration), WTFMove(implementation)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-const MediaKeySystemConfiguration&amp; MediaKeySystemAccess::getConfiguration() const
</del><ins>+MediaKeySystemAccess::MediaKeySystemAccess(const String&amp; keySystem, MediaKeySystemConfiguration&amp;&amp; configuration, Ref&lt;CDM&gt;&amp;&amp; implementation)
+    : m_keySystem(keySystem)
+    , m_configuration(new MediaKeySystemConfiguration(WTFMove(configuration)))
+    , m_implementation(WTFMove(implementation))
</ins><span class="cx"> {
</span><del>-    notImplemented();
-    return m_configuration;
</del><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MediaKeySystemAccess::~MediaKeySystemAccess() = default;
+
</ins><span class="cx"> void MediaKeySystemAccess::createMediaKeys(Ref&lt;DeferredPromise&gt;&amp;&amp;)
</span><span class="cx"> {
</span><span class="cx">     notImplemented();
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySystemAccessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -31,32 +31,31 @@
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSDOMPromise.h&quot;
</span><del>-#include &quot;MediaKeySystemConfiguration.h&quot;
</del><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class CDM;
</ins><span class="cx"> class MediaKeys;
</span><span class="cx"> 
</span><ins>+struct MediaKeySystemConfiguration;
+
</ins><span class="cx"> class MediaKeySystemAccess : public RefCounted&lt;MediaKeySystemAccess&gt; {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;MediaKeySystemAccess&gt; create()
-    {
-        return adoptRef(*new MediaKeySystemAccess);
-    }
</del><ins>+    static Ref&lt;MediaKeySystemAccess&gt; create(const String&amp; keySystem, MediaKeySystemConfiguration&amp;&amp;, Ref&lt;CDM&gt;&amp;&amp;);
+    ~MediaKeySystemAccess();
</ins><span class="cx"> 
</span><del>-    virtual ~MediaKeySystemAccess();
-
-    const String&amp; keySystem() const;
-    const MediaKeySystemConfiguration&amp; getConfiguration() const;
</del><ins>+    const String&amp; keySystem() const { return m_keySystem; }
+    const MediaKeySystemConfiguration&amp; getConfiguration() const { return *m_configuration; }
</ins><span class="cx">     void createMediaKeys(Ref&lt;DeferredPromise&gt;&amp;&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    MediaKeySystemAccess();
</del><ins>+    MediaKeySystemAccess(const String&amp; keySystem, MediaKeySystemConfiguration&amp;&amp;, Ref&lt;CDM&gt;&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     String m_keySystem;
</span><del>-    MediaKeySystemConfiguration m_configuration;
</del><ins>+    std::unique_ptr&lt;MediaKeySystemConfiguration&gt; m_configuration;
+    Ref&lt;CDM&gt; m_implementation;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySystemAccessidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -28,9 +28,10 @@
</span><span class="cx"> 
</span><span class="cx"> [
</span><span class="cx">     Conditional=ENCRYPTED_MEDIA,
</span><del>-    EnabledAtRuntime=EncryptedMediaAPI
</del><ins>+    EnabledAtRuntime=EncryptedMediaAPI,
+    ImplementationLacksVTable,
</ins><span class="cx"> ] interface MediaKeySystemAccess {
</span><span class="cx">     readonly attribute DOMString keySystem;
</span><del>-    [Custom] MediaKeySystemConfiguration getConfiguration();
</del><ins>+    MediaKeySystemConfiguration getConfiguration();
</ins><span class="cx">     Promise&lt;MediaKeys&gt; createMediaKeys();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySystemConfigurationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="cx"> 
</span><ins>+#include &quot;MediaKeySessionType.h&quot;
</ins><span class="cx"> #include &quot;MediaKeySystemMediaCapability.h&quot;
</span><span class="cx"> #include &quot;MediaKeysRequirement.h&quot;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -46,7 +47,7 @@
</span><span class="cx">     Vector&lt;MediaKeySystemMediaCapability&gt; videoCapabilities;
</span><span class="cx">     MediaKeysRequirement distinctiveIdentifier;
</span><span class="cx">     MediaKeysRequirement persistentState;
</span><del>-    Vector&lt;String&gt; sessionTypes;
</del><ins>+    Vector&lt;MediaKeySessionType&gt; sessionTypes;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySystemConfigurationidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemConfiguration.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -26,14 +26,9 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-enum MediaKeysRequirement {
-    &quot;required&quot;,
-    &quot;optional&quot;,
-    &quot;not-allowed&quot;
-};
-
</del><span class="cx"> [
</span><del>-    Conditional=ENCRYPTED_MEDIA
</del><ins>+    Conditional=ENCRYPTED_MEDIA,
+    JSGenerateToJSObject
</ins><span class="cx"> ] dictionary MediaKeySystemConfiguration {
</span><span class="cx">     DOMString label = &quot;&quot;;
</span><span class="cx">     sequence&lt;DOMString&gt; initDataTypes = [];
</span><span class="lines">@@ -41,5 +36,5 @@
</span><span class="cx">     sequence&lt;MediaKeySystemMediaCapability&gt; videoCapabilities = [];
</span><span class="cx">     MediaKeysRequirement distinctiveIdentifier = &quot;optional&quot;;
</span><span class="cx">     MediaKeysRequirement persistentState = &quot;optional&quot;;
</span><del>-    sequence&lt;DOMString&gt; sessionTypes;
</del><ins>+    sequence&lt;MediaKeySessionType&gt; sessionTypes;
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySystemMediaCapabilityidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemMediaCapability.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -27,7 +27,8 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> [
</span><del>-    Conditional=ENCRYPTED_MEDIA
</del><ins>+    Conditional=ENCRYPTED_MEDIA,
+    JSGenerateToJSObject,
</ins><span class="cx"> ] dictionary MediaKeySystemMediaCapability {
</span><span class="cx">     DOMString contentType = &quot;&quot;;
</span><span class="cx">     DOMString robustness = &quot;&quot;;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeysidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -26,12 +26,6 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-enum MediaKeySessionType {
-    &quot;temporary&quot;,
-    &quot;persistent-usage-record&quot;,
-    &quot;persistent-license&quot;
-};

</del><span class="cx"> [
</span><span class="cx">     Conditional=ENCRYPTED_MEDIA,
</span><span class="cx">     EnabledAtRuntime=EncryptedMediaAPI
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeysRequirementidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRequirement.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=ENCRYPTED_MEDIA,
+    ImplementedAs=MediaKeysRequirement,
+    ExportMacro=WEBCORE_TESTSUPPORT_EXPORT
+]
+enum MediaKeysRequirement {
+    &quot;required&quot;,
+    &quot;optional&quot;,
+    &quot;not-allowed&quot;
+};
+
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeysRestrictionsh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeysRestrictions.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include &lt;wtf/HashSet.h&gt;
+
+namespace WebCore {
+
+struct MediaKeysRestrictions {
+    bool distinctiveIdentifierDenied { false };
+    bool persistentStateDenied { false };
+    HashSet&lt;String&gt; deniedSessionTypes;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaNavigatorEMEcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.cpp        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -31,15 +31,80 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="cx"> 
</span><ins>+#include &quot;CDM.h&quot;
+#include &quot;Document.h&quot;
+#include &quot;JSMediaKeySystemAccess.h&quot;
</ins><span class="cx"> #include &quot;NotImplemented.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-void NavigatorEME::requestMediaKeySystemAccess(Navigator&amp;, const String&amp;, Vector&lt;MediaKeySystemConfiguration&gt;&amp;&amp;, Ref&lt;DeferredPromise&gt;&amp;&amp;)
</del><ins>+static void tryNextSupportedConfiguration(RefPtr&lt;CDM&gt;&amp;&amp; implementation, Vector&lt;MediaKeySystemConfiguration&gt;&amp;&amp; supportedConfigurations, RefPtr&lt;DeferredPromise&gt;&amp;&amp;);
+
+void NavigatorEME::requestMediaKeySystemAccess(Navigator&amp;, Document&amp; document, const String&amp; keySystem, Vector&lt;MediaKeySystemConfiguration&gt;&amp;&amp; supportedConfigurations, Ref&lt;DeferredPromise&gt;&amp;&amp; promise)
</ins><span class="cx"> {
</span><del>-    notImplemented();
</del><ins>+    // https://w3c.github.io/encrypted-media/#dom-navigator-requestmediakeysystemaccess
+    // W3C Editor's Draft 09 November 2016
+
+    // When this method is invoked, the user agent must run the following steps:
+    // 1. If keySystem is the empty string, return a promise rejected with a newly created TypeError.
+    // 2. If supportedConfigurations is empty, return a promise rejected with a newly created TypeError.
+    if (keySystem.isEmpty() || supportedConfigurations.isEmpty()) {
+        promise-&gt;reject(TypeError);
+        return;
+    }
+
+    document.postTask([keySystem, supportedConfigurations = WTFMove(supportedConfigurations), promise = WTFMove(promise), &amp;document] (ScriptExecutionContext&amp;) mutable {
+        // 3. Let document be the calling context's Document.
+        // 4. Let origin be the origin of document.
+        // 5. Let promise be a new promise.
+        // 6. Run the following steps in parallel:
+        // 6.1. If keySystem is not one of the Key Systems supported by the user agent, reject promise with a NotSupportedError.
+        //      String comparison is case-sensitive.
+        if (!CDM::supportsKeySystem(keySystem)) {
+            promise-&gt;reject(NOT_SUPPORTED_ERR);
+            return;
+        }
+
+        // 6.2. Let implementation be the implementation of keySystem.
+        RefPtr&lt;CDM&gt; implementation = CDM::create(document, keySystem);
+        tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise));
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void tryNextSupportedConfiguration(RefPtr&lt;CDM&gt;&amp;&amp; implementation, Vector&lt;MediaKeySystemConfiguration&gt;&amp;&amp; supportedConfigurations, RefPtr&lt;DeferredPromise&gt;&amp;&amp; promise)
+{
+    // 6.3. For each value in supportedConfigurations:
+    if (!supportedConfigurations.isEmpty()) {
+        // 6.3.1. Let candidate configuration be the value.
+        // 6.3.2. Let supported configuration be the result of executing the Get Supported Configuration
+        //        algorithm on implementation, candidate configuration, and origin.
+        MediaKeySystemConfiguration candidateCofiguration = WTFMove(supportedConfigurations.first());
+        supportedConfigurations.remove(0);
+
+        CDM::SupportedConfigurationCallback callback = [implementation = implementation, supportedConfigurations = WTFMove(supportedConfigurations), promise] (std::optional&lt;MediaKeySystemConfiguration&gt; supportedConfiguration) mutable {
+            // 6.3.3. If supported configuration is not NotSupported, run the following steps:
+            if (supportedConfiguration) {
+                // 6.3.3.1. Let access be a new MediaKeySystemAccess object, and initialize it as follows:
+                // 6.3.3.1.1. Set the keySystem attribute to keySystem.
+                // 6.3.3.1.2. Let the configuration value be supported configuration.
+                // 6.3.3.1.3. Let the cdm implementation value be implementation.
+                auto access = MediaKeySystemAccess::create(implementation-&gt;keySystem(), WTFMove(supportedConfiguration.value()), implementation.releaseNonNull());
+                // 6.3.3.2. Resolve promise with access and abort the parallel steps of this algorithm.
+                promise-&gt;resolve&lt;IDLInterface&lt;MediaKeySystemAccess&gt;&gt;(access.get());
+                return;
+            }
+
+            tryNextSupportedConfiguration(WTFMove(implementation), WTFMove(supportedConfigurations), WTFMove(promise));
+        };
+        implementation-&gt;getSupportedConfiguration(WTFMove(candidateCofiguration), WTFMove(callback));
+        return;
+    }
+
+
+    // 6.4. Reject promise with a NotSupportedError.
+    promise-&gt;reject(NOT_SUPPORTED_ERR);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(ENCRYPTED_MEDIA)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaNavigatorEMEh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> class NavigatorEME final : public Supplement&lt;Page&gt; {
</span><span class="cx"> public:
</span><del>-    static void requestMediaKeySystemAccess(Navigator&amp;, const String&amp;, Vector&lt;MediaKeySystemConfiguration&gt;&amp;&amp;, Ref&lt;DeferredPromise&gt;&amp;&amp;);
</del><ins>+    static void requestMediaKeySystemAccess(Navigator&amp;, Document&amp;, const String&amp;, Vector&lt;MediaKeySystemConfiguration&gt;&amp;&amp;, Ref&lt;DeferredPromise&gt;&amp;&amp;);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaNavigatorEMEidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/Modules/encryptedmedia/NavigatorEME.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -30,5 +30,5 @@
</span><span class="cx">     Conditional=ENCRYPTED_MEDIA,
</span><span class="cx">     EnabledAtRuntime=EncryptedMediaAPI
</span><span class="cx"> ] partial interface Navigator {
</span><del>-    Promise&lt;MediaKeySystemAccess&gt; requestMediaKeySystemAccess(DOMString keySystem, sequence&lt;MediaKeySystemConfiguration&gt; supportedConfiguration);
</del><ins>+    [CallWith=Document] Promise&lt;MediaKeySystemAccess&gt; requestMediaKeySystemAccess(DOMString keySystem, sequence&lt;MediaKeySystemConfiguration&gt; supportedConfiguration);
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1243,7 +1243,6 @@
</span><span class="cx">                 2D9BF7461DBFDC47007A7D99 /* MediaKeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BF7331DBFDC0F007A7D99 /* MediaKeys.cpp */; };
</span><span class="cx">                 2D9BF7471DBFDC49007A7D99 /* MediaKeyMessageEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BF72F1DBFDC0F007A7D99 /* MediaKeyMessageEvent.cpp */; };
</span><span class="cx">                 2D9BF74A1DBFDDFF007A7D99 /* JSMediaKeySessionCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BF7481DBFDDF8007A7D99 /* JSMediaKeySessionCustom.cpp */; };
</span><del>-                2D9BF74B1DBFDE02007A7D99 /* JSMediaKeySystemAccessCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BF7491DBFDDF8007A7D99 /* JSMediaKeySystemAccessCustom.cpp */; };
</del><span class="cx">                 2D9F0E1314FF1CBF00BA0FF7 /* linearSRGB.icc in Resources */ = {isa = PBXBuildFile; fileRef = 2D9F0E1214FF1CBF00BA0FF7 /* linearSRGB.icc */; };
</span><span class="cx">                 2DB9C4AA1B3231F40070F27F /* NSEventSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DB9C4A91B3231F40070F27F /* NSEventSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 2DC4CF791D2DD98900ECCC94 /* DataDetectorsUISPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DC4CF781D2DD98900ECCC94 /* DataDetectorsUISPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -5910,6 +5909,22 @@
</span><span class="cx">                 CDF2B0171820540700F2B424 /* MockSourceBufferPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF2B00D1820540600F2B424 /* MockSourceBufferPrivate.h */; };
</span><span class="cx">                 CDF2B0191820540700F2B424 /* MockTracks.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF2B00F1820540600F2B424 /* MockTracks.h */; };
</span><span class="cx">                 CDF4B7121E0087AE00E235A2 /* LegacyCDMSession.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE02E918B3DFC700CF7FF1 /* LegacyCDMSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                CDF4B7151E00B7E500E235A2 /* CDM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF4B7131E00B7E500E235A2 /* CDM.cpp */; };
+                CDF4B7161E00B7E500E235A2 /* CDM.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B7141E00B7E500E235A2 /* CDM.h */; };
+                CDF4B7181E01CB9100E235A2 /* MediaKeysRestrictions.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B7171E01CB9100E235A2 /* MediaKeysRestrictions.h */; };
+                CDF4B71A1E01D3D000E235A2 /* MediaKeySessionType.idl in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B7191E01D3D000E235A2 /* MediaKeySessionType.idl */; };
+                CDF4B71D1E01E11A00E235A2 /* JSMediaKeySessionType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF4B71B1E01E11A00E235A2 /* JSMediaKeySessionType.cpp */; };
+                CDF4B71E1E01E11A00E235A2 /* JSMediaKeySessionType.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B71C1E01E11A00E235A2 /* JSMediaKeySessionType.h */; };
+                CDF4B7201E03BF6F00E235A2 /* MockCDMFactory.idl in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B71F1E03BF6F00E235A2 /* MockCDMFactory.idl */; };
+                CDF4B7241E03BF8100E235A2 /* MockCDMFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B7221E03BF8100E235A2 /* MockCDMFactory.h */; };
+                CDF4B7261E03C15B00E235A2 /* CDMPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B7251E03C15B00E235A2 /* CDMPrivate.h */; };
+                CDF4B7281E03C57300E235A2 /* MediaKeysRequirement.idl in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B7271E03C57300E235A2 /* MediaKeysRequirement.idl */; };
+                CDF4B72B1E03C63E00E235A2 /* JSMediaKeysRequirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF4B7291E03C63E00E235A2 /* JSMediaKeysRequirement.cpp */; };
+                CDF4B72C1E03C63E00E235A2 /* JSMediaKeysRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B72A1E03C63E00E235A2 /* JSMediaKeysRequirement.h */; };
+                CDF4B7301E03CA4A00E235A2 /* JSMockCDMFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF4B72E1E03CA4A00E235A2 /* JSMockCDMFactory.h */; };
+                CDF4B7311E03D00700E235A2 /* MockCDMFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF4B7211E03BF8100E235A2 /* MockCDMFactory.cpp */; };
+                CDF4B7321E03D06000E235A2 /* JSMockCDMFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF4B72D1E03CA4A00E235A2 /* JSMockCDMFactory.cpp */; };
+                CDF4B7331E03D14900E235A2 /* JSMediaKeysRequirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF4B7291E03C63E00E235A2 /* JSMediaKeysRequirement.cpp */; };
</ins><span class="cx">                 CDF65CC8145B1E7500C4C7AA /* MediaController.h in Headers */ = {isa = PBXBuildFile; fileRef = CD27F6E4145767870078207D /* MediaController.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CDF65CCA145B448800C4C7AA /* MediaControllerInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF65CC9145B43A700C4C7AA /* MediaControllerInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CDF7483E18FEBCEC0006ECC0 /* GridPositionsResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF7483C18FEBCEC0006ECC0 /* GridPositionsResolver.cpp */; };
</span><span class="lines">@@ -8374,7 +8389,6 @@
</span><span class="cx">                 2D9BF7401DBFDC0F007A7D99 /* NavigatorEME.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorEME.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D9BF7411DBFDC0F007A7D99 /* NavigatorEME.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorEME.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D9BF7481DBFDDF8007A7D99 /* JSMediaKeySessionCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeySessionCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                2D9BF7491DBFDDF8007A7D99 /* JSMediaKeySystemAccessCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeySystemAccessCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 2D9F0E1214FF1CBF00BA0FF7 /* linearSRGB.icc */ = {isa = PBXFileReference; lastKnownFileType = file; path = linearSRGB.icc; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2DAAE32C19DCAF6000E002D2 /* MockPageOverlayClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockPageOverlayClient.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2DAAE32D19DCAF6000E002D2 /* MockPageOverlayClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockPageOverlayClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -13878,6 +13892,21 @@
</span><span class="cx">                 CDF2B00D1820540600F2B424 /* MockSourceBufferPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockSourceBufferPrivate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDF2B00F1820540600F2B424 /* MockTracks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockTracks.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDF419991AB0DA14004E64E1 /* missingImage@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = &quot;missingImage@3x.png&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                CDF4B7131E00B7E500E235A2 /* CDM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDM.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7141E00B7E500E235A2 /* CDM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDM.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7171E01CB9100E235A2 /* MediaKeysRestrictions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaKeysRestrictions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7191E01D3D000E235A2 /* MediaKeySessionType.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaKeySessionType.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B71B1E01E11A00E235A2 /* JSMediaKeySessionType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeySessionType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B71C1E01E11A00E235A2 /* JSMediaKeySessionType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaKeySessionType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B71F1E03BF6F00E235A2 /* MockCDMFactory.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MockCDMFactory.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7211E03BF8100E235A2 /* MockCDMFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockCDMFactory.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7221E03BF8100E235A2 /* MockCDMFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockCDMFactory.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7251E03C15B00E235A2 /* CDMPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMPrivate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7271E03C57300E235A2 /* MediaKeysRequirement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaKeysRequirement.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B7291E03C63E00E235A2 /* JSMediaKeysRequirement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeysRequirement.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B72A1E03C63E00E235A2 /* JSMediaKeysRequirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaKeysRequirement.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B72D1E03CA4A00E235A2 /* JSMockCDMFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMockCDMFactory.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDF4B72E1E03CA4A00E235A2 /* JSMockCDMFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMockCDMFactory.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 CDF65CC9145B43A700C4C7AA /* MediaControllerInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaControllerInterface.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDF65CCC145B6AFE00C4C7AA /* JSHTMLMediaElementCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLMediaElementCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDF7483C18FEBCEC0006ECC0 /* GridPositionsResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GridPositionsResolver.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -16564,6 +16593,9 @@
</span><span class="cx">                                 A7BF7EDC14C9175A0014489D /* InternalSettings.cpp */,
</span><span class="cx">                                 A7BF7EDD14C9175A0014489D /* InternalSettings.h */,
</span><span class="cx">                                 A7BF7EDE14C9175A0014489D /* InternalSettings.idl */,
</span><ins>+                                CDF4B71F1E03BF6F00E235A2 /* MockCDMFactory.idl */,
+                                CDF4B7211E03BF8100E235A2 /* MockCDMFactory.cpp */,
+                                CDF4B7221E03BF8100E235A2 /* MockCDMFactory.h */,
</ins><span class="cx">                                 A7BE7EDD14C9175A0014489D /* MallocStatistics.h */,
</span><span class="cx">                                 A7BE7EDE14C9175A0014489D /* MallocStatistics.idl */,
</span><span class="cx">                                 CD5393CB175DCCE600C07123 /* MemoryInfo.h */,
</span><span class="lines">@@ -16606,6 +16638,8 @@
</span><span class="cx">                                 A7B4EA6914C9348400C8F5BF /* JSMallocStatistics.h */,
</span><span class="cx">                                 CD5393D1175E018600C07123 /* JSMemoryInfo.cpp */,
</span><span class="cx">                                 CD5393D2175E018600C07123 /* JSMemoryInfo.h */,
</span><ins>+                                CDF4B72D1E03CA4A00E235A2 /* JSMockCDMFactory.cpp */,
+                                CDF4B72E1E03CA4A00E235A2 /* JSMockCDMFactory.h */,
</ins><span class="cx">                                 A19AEA1D1AAA806E00B52B25 /* JSMockContentFilterSettings.cpp */,
</span><span class="cx">                                 A19AEA1E1AAA806E00B52B25 /* JSMockContentFilterSettings.h */,
</span><span class="cx">                                 2D6F3E921C1F85550061DBD4 /* JSMockPageOverlay.cpp */,
</span><span class="lines">@@ -21995,7 +22029,6 @@
</span><span class="cx">                                 8F934D831189F1EE00508D5D /* JSMainThreadExecState.h */,
</span><span class="cx">                                 B56576E417DA599F00A56BDC /* JSMainThreadExecStateInstrumentation.h */,
</span><span class="cx">                                 2D9BF7481DBFDDF8007A7D99 /* JSMediaKeySessionCustom.cpp */,
</span><del>-                                2D9BF7491DBFDDF8007A7D99 /* JSMediaKeySystemAccessCustom.cpp */,
</del><span class="cx">                                 C6F420A016B7164E0052A9F2 /* JSMutationCallback.cpp */,
</span><span class="cx">                                 C6F420A116B7164E0052A9F2 /* JSMutationCallback.h */,
</span><span class="cx">                                 CB38FD551CD21D5B00592A3F /* JSPerformanceEntryCustom.cpp */,
</span><span class="lines">@@ -22762,6 +22795,9 @@
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><span class="cx">                                 2D0621461DA639EC00A7FB26 /* legacy */,
</span><ins>+                                CDF4B7131E00B7E500E235A2 /* CDM.cpp */,
+                                CDF4B7141E00B7E500E235A2 /* CDM.h */,
+                                CDF4B7251E03C15B00E235A2 /* CDMPrivate.h */,
</ins><span class="cx">                                 2D9BF72F1DBFDC0F007A7D99 /* MediaKeyMessageEvent.cpp */,
</span><span class="cx">                                 2D9BF7301DBFDC0F007A7D99 /* MediaKeyMessageEvent.h */,
</span><span class="cx">                                 2D9BF6F51DBFB71F007A7D99 /* MediaKeyMessageEvent.idl */,
</span><span class="lines">@@ -22774,7 +22810,10 @@
</span><span class="cx">                                 2D9BF7361DBFDC0F007A7D99 /* MediaKeySession.h */,
</span><span class="cx">                                 2D9BF6F71DBFB71F007A7D99 /* MediaKeySession.idl */,
</span><span class="cx">                                 2D9BF7371DBFDC0F007A7D99 /* MediaKeySessionType.h */,
</span><ins>+                                CDF4B7191E01D3D000E235A2 /* MediaKeySessionType.idl */,
</ins><span class="cx">                                 2D9BF7381DBFDC0F007A7D99 /* MediaKeysRequirement.h */,
</span><ins>+                                CDF4B7271E03C57300E235A2 /* MediaKeysRequirement.idl */,
+                                CDF4B7171E01CB9100E235A2 /* MediaKeysRestrictions.h */,
</ins><span class="cx">                                 2D9BF7391DBFDC0F007A7D99 /* MediaKeyStatus.h */,
</span><span class="cx">                                 2D9BF73A1DBFDC0F007A7D99 /* MediaKeyStatusMap.cpp */,
</span><span class="cx">                                 2D9BF73B1DBFDC0F007A7D99 /* MediaKeyStatusMap.h */,
</span><span class="lines">@@ -22802,6 +22841,8 @@
</span><span class="cx">                                 2D9BF7161DBFDAB1007A7D99 /* JSMediaKeys.h */,
</span><span class="cx">                                 2D9BF7171DBFDAB1007A7D99 /* JSMediaKeySession.cpp */,
</span><span class="cx">                                 2D9BF7181DBFDAB1007A7D99 /* JSMediaKeySession.h */,
</span><ins>+                                CDF4B71B1E01E11A00E235A2 /* JSMediaKeySessionType.cpp */,
+                                CDF4B71C1E01E11A00E235A2 /* JSMediaKeySessionType.h */,
</ins><span class="cx">                                 2D9BF7191DBFDAB1007A7D99 /* JSMediaKeyStatusMap.cpp */,
</span><span class="cx">                                 2D9BF71A1DBFDAB1007A7D99 /* JSMediaKeyStatusMap.h */,
</span><span class="cx">                                 2D9BF71B1DBFDAB1007A7D99 /* JSMediaKeySystemAccess.cpp */,
</span><span class="lines">@@ -22810,6 +22851,8 @@
</span><span class="cx">                                 2D9BF71E1DBFDAB1007A7D99 /* JSMediaKeySystemConfiguration.h */,
</span><span class="cx">                                 2D9BF71F1DBFDAB1007A7D99 /* JSMediaKeySystemMediaCapability.cpp */,
</span><span class="cx">                                 2D9BF7201DBFDAB1007A7D99 /* JSMediaKeySystemMediaCapability.h */,
</span><ins>+                                CDF4B7291E03C63E00E235A2 /* JSMediaKeysRequirement.cpp */,
+                                CDF4B72A1E03C63E00E235A2 /* JSMediaKeysRequirement.h */,
</ins><span class="cx">                                 CDA98D9B160128A500FEA3B1 /* JSWebKitMediaKeyError.cpp */,
</span><span class="cx">                                 CDA98D9C160128A500FEA3B1 /* JSWebKitMediaKeyError.h */,
</span><span class="cx">                                 CDA98DDB16026A1800FEA3B1 /* JSWebKitMediaKeyMessageEvent.cpp */,
</span><span class="lines">@@ -25451,6 +25494,7 @@
</span><span class="cx">                                 76FC2B0C12370DA0006A991A /* DOMTokenList.h in Headers */,
</span><span class="cx">                                 2E37DFDB12DBAFB800A6B233 /* DOMURL.h in Headers */,
</span><span class="cx">                                 CD9DE18217AAD6A400EA386D /* DOMURLMediaSource.h in Headers */,
</span><ins>+                                CDF4B7241E03BF8100E235A2 /* MockCDMFactory.h in Headers */,
</ins><span class="cx">                                 15FCC9FE1B4DF85E00E72326 /* DOMURLMediaStream.h in Headers */,
</span><span class="cx">                                 1403B99709EB13AF00797C7F /* DOMWindow.h in Headers */,
</span><span class="cx">                                 51FA2D78152132B300C1BA0B /* DOMWindowExtension.h in Headers */,
</span><span class="lines">@@ -25646,6 +25690,7 @@
</span><span class="cx">                                 FD31600D12B0267600C1A359 /* GainNode.h in Headers */,
</span><span class="cx">                                 51E399001D6E4750009C8831 /* GameControllerGamepad.h in Headers */,
</span><span class="cx">                                 51E399021D6E4750009C8831 /* GameControllerGamepadProvider.h in Headers */,
</span><ins>+                                CDF4B71E1E01E11A00E235A2 /* JSMediaKeySessionType.h in Headers */,
</ins><span class="cx">                                 516C62211950D48700337E75 /* GamepadEvent.h in Headers */,
</span><span class="cx">                                 51A9D9EA195B931F001B2B5C /* GamepadManager.h in Headers */,
</span><span class="cx">                                 515BE1921D54F5FB00DD7C68 /* GamepadProvider.h in Headers */,
</span><span class="lines">@@ -25783,6 +25828,7 @@
</span><span class="cx">                                 A8DF3FD4097FA0FC0052981B /* HTMLNameCollection.h in Headers */,
</span><span class="cx">                                 A871D45A0A127CBC00B12A68 /* HTMLObjectElement.h in Headers */,
</span><span class="cx">                                 A8EA79F10A1916DF00A8EF5F /* HTMLOListElement.h in Headers */,
</span><ins>+                                CDF4B7201E03BF6F00E235A2 /* MockCDMFactory.idl in Headers */,
</ins><span class="cx">                                 A81369DE097374F600D74463 /* HTMLOptGroupElement.h in Headers */,
</span><span class="cx">                                 A81369DC097374F600D74463 /* HTMLOptionElement.h in Headers */,
</span><span class="cx">                                 A81369DA097374F600D74463 /* HTMLOptionsCollection.h in Headers */,
</span><span class="lines">@@ -26015,6 +26061,7 @@
</span><span class="cx">                                 3198480C1A1E6CE800A13318 /* JSAnimationEvent.h in Headers */,
</span><span class="cx">                                 1221E06D1C03D224006A1A00 /* JSAnimationTimeline.h in Headers */,
</span><span class="cx">                                 1AE96A8B1D1A0DDD00B86768 /* JSApplePayPaymentAuthorizedEvent.h in Headers */,
</span><ins>+                                CDF4B7301E03CA4A00E235A2 /* JSMockCDMFactory.h in Headers */,
</ins><span class="cx">                                 1AE96A8D1D1A0DDD00B86768 /* JSApplePayPaymentMethodSelectedEvent.h in Headers */,
</span><span class="cx">                                 1AE96A8F1D1A0DDD00B86768 /* JSApplePaySession.h in Headers */,
</span><span class="cx">                                 1AE96A911D1A0DDD00B86768 /* JSApplePayShippingContactSelectedEvent.h in Headers */,
</span><span class="lines">@@ -26461,6 +26508,7 @@
</span><span class="cx">                                 B266CD4E0C3AEC6500EB08D2 /* JSSVGException.h in Headers */,
</span><span class="cx">                                 B2FA3D6B0AB75A6F000E5AC4 /* JSSVGFEBlendElement.h in Headers */,
</span><span class="cx">                                 B2FA3D6D0AB75A6F000E5AC4 /* JSSVGFEColorMatrixElement.h in Headers */,
</span><ins>+                                CDF4B7261E03C15B00E235A2 /* CDMPrivate.h in Headers */,
</ins><span class="cx">                                 B2FA3D6F0AB75A6F000E5AC4 /* JSSVGFEComponentTransferElement.h in Headers */,
</span><span class="cx">                                 B2FA3D710AB75A6F000E5AC4 /* JSSVGFECompositeElement.h in Headers */,
</span><span class="cx">                                 19BFF64F11C0F2AC00B8C04D /* JSSVGFEConvolveMatrixElement.h in Headers */,
</span><span class="lines">@@ -26600,6 +26648,7 @@
</span><span class="cx">                                 49C7B9941042D2D30009D447 /* JSWebGLBuffer.h in Headers */,
</span><span class="cx">                                 7EA30F6A16DFFE7500257D0B /* JSWebGLCompressedTextureATC.h in Headers */,
</span><span class="cx">                                 7EA30F6A17EFFE7500257D0B /* JSWebGLCompressedTexturePVRTC.h in Headers */,
</span><ins>+                                CDF4B7281E03C57300E235A2 /* MediaKeysRequirement.idl in Headers */,
</ins><span class="cx">                                 6E3FAD3914733F4000E42306 /* JSWebGLCompressedTextureS3TC.h in Headers */,
</span><span class="cx">                                 6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */,
</span><span class="cx">                                 BC2CBF4E140F1ABD003879BE /* JSWebGLContextEvent.h in Headers */,
</span><span class="lines">@@ -26699,6 +26748,7 @@
</span><span class="cx">                                 FFDBC047183D27B700407109 /* LineWidth.h in Headers */,
</span><span class="cx">                                 A7AD2F880EC89D07008AB002 /* LinkHash.h in Headers */,
</span><span class="cx">                                 5143B2631DDD15200014FAC6 /* LinkIcon.h in Headers */,
</span><ins>+                                CDF4B72C1E03C63E00E235A2 /* JSMediaKeysRequirement.h in Headers */,
</ins><span class="cx">                                 1A4DA4221CDD3A8300F4473C /* LinkIconCollector.h in Headers */,
</span><span class="cx">                                 1A250E0D1CDD632000D0BE63 /* LinkIconType.h in Headers */,
</span><span class="cx">                                 98CE432A129E00E5005821DC /* LinkLoader.h in Headers */,
</span><span class="lines">@@ -26844,6 +26894,7 @@
</span><span class="cx">                                 51E1BAC31BD8064E0055D81F /* MemoryBackingStoreTransaction.h in Headers */,
</span><span class="cx">                                 BCB16C180979C3BD00467741 /* MemoryCache.h in Headers */,
</span><span class="cx">                                 517139081BF64DEF000D5F01 /* MemoryCursor.h in Headers */,
</span><ins>+                                CDF4B71A1E01D3D000E235A2 /* MediaKeySessionType.idl in Headers */,
</ins><span class="cx">                                 51BA4ACB1BBC5BD900DF3D6D /* MemoryIDBBackingStore.h in Headers */,
</span><span class="cx">                                 518F97031BE94C630023187C /* MemoryIndex.h in Headers */,
</span><span class="cx">                                 519755FA1BFD7DC3003DE980 /* MemoryIndexCursor.h in Headers */,
</span><span class="lines">@@ -28059,6 +28110,7 @@
</span><span class="cx">                                 85031B4F0A44EFC700F992E0 /* UIEventWithKeyState.h in Headers */,
</span><span class="cx">                                 A1ED778F1BE4291800DC1791 /* UIKitSPI.h in Headers */,
</span><span class="cx">                                 AA4739D21757AFEC00E76767 /* UIRequestEvent.h in Headers */,
</span><ins>+                                CDF4B7161E00B7E500E235A2 /* CDM.h in Headers */,
</ins><span class="cx">                                 9B2D8A7914997CCF00ECEF3E /* UndoStep.h in Headers */,
</span><span class="cx">                                 A863E2011343412000274926 /* UnicodeBidi.h in Headers */,
</span><span class="cx">                                 518864E11BBAF57400E540C9 /* UniqueIDBDatabase.h in Headers */,
</span><span class="lines">@@ -28357,6 +28409,7 @@
</span><span class="cx">                                 1AB7FC7D0A8B92EC00D9D37B /* XPathPredicate.h in Headers */,
</span><span class="cx">                                 1AB7FC7F0A8B92EC00D9D37B /* XPathResult.h in Headers */,
</span><span class="cx">                                 1AB7FC820A8B92EC00D9D37B /* XPathStep.h in Headers */,
</span><ins>+                                CDF4B7181E01CB9100E235A2 /* MediaKeysRestrictions.h in Headers */,
</ins><span class="cx">                                 1AB7FC840A8B92EC00D9D37B /* XPathUtil.h in Headers */,
</span><span class="cx">                                 1AB7FC860A8B92EC00D9D37B /* XPathValue.h in Headers */,
</span><span class="cx">                                 1AB7FC880A8B92EC00D9D37B /* XPathVariableReference.h in Headers */,
</span><span class="lines">@@ -28661,6 +28714,7 @@
</span><span class="cx">                                 A740B5A714C935AF00A77FA4 /* JSInternalSettings.cpp in Sources */,
</span><span class="cx">                                 53ED3FDE167A88E7006762E6 /* JSInternalSettingsGenerated.cpp in Sources */,
</span><span class="cx">                                 A740B59714C935AF00A77FA4 /* JSMallocStatistics.cpp in Sources */,
</span><ins>+                                CDF4B7331E03D14900E235A2 /* JSMediaKeysRequirement.cpp in Sources */,
</ins><span class="cx">                                 CD5393D3175E018600C07123 /* JSMemoryInfo.cpp in Sources */,
</span><span class="cx">                                 A19AEA221AAA808A00B52B25 /* JSMockContentFilterSettings.cpp in Sources */,
</span><span class="cx">                                 A1E5B31F1AAD1DA4006EBEFB /* JSMockContentFilterSettingsCustom.cpp in Sources */,
</span><span class="lines">@@ -28671,7 +28725,9 @@
</span><span class="cx">                                 A1B5B29E1AAA846E008B6042 /* MockContentFilterSettings.cpp in Sources */,
</span><span class="cx">                                 51058ADB1D6792C1009A538C /* MockGamepad.cpp in Sources */,
</span><span class="cx">                                 51058ADD1D6792C1009A538C /* MockGamepadProvider.cpp in Sources */,
</span><ins>+                                CDF4B7311E03D00700E235A2 /* MockCDMFactory.cpp in Sources */,
</ins><span class="cx">                                 2D6F3E901C1ECB270061DBD4 /* MockPageOverlay.cpp in Sources */,
</span><ins>+                                CDF4B7321E03D06000E235A2 /* JSMockCDMFactory.cpp in Sources */,
</ins><span class="cx">                                 2D97F04719DD413C001EE9C3 /* MockPageOverlayClient.cpp in Sources */,
</span><span class="cx">                                 AA5F3B8F16CC4B3900455EB0 /* PlatformSpeechSynthesizerMock.cpp in Sources */,
</span><span class="cx">                                 41815C1E138319830057AAA4 /* WebCoreTestSupport.cpp in Sources */,
</span><span class="lines">@@ -28777,6 +28833,7 @@
</span><span class="cx">                                 FD31601512B0267600C1A359 /* AudioNodeInput.cpp in Sources */,
</span><span class="cx">                                 FD31601712B0267600C1A359 /* AudioNodeOutput.cpp in Sources */,
</span><span class="cx">                                 FD31601C12B0267600C1A359 /* AudioParam.cpp in Sources */,
</span><ins>+                                CDF4B7151E00B7E500E235A2 /* CDM.cpp in Sources */,
</ins><span class="cx">                                 FD35918F138DB22000E1EBEC /* AudioParamTimeline.cpp in Sources */,
</span><span class="cx">                                 FD31601F12B0267600C1A359 /* AudioProcessingEvent.cpp in Sources */,
</span><span class="cx">                                 FD31608512B026F700C1A359 /* AudioResampler.cpp in Sources */,
</span><span class="lines">@@ -29296,6 +29353,7 @@
</span><span class="cx">                                 84730D7A1248F0B300D3A9C9 /* FEDiffuseLighting.cpp in Sources */,
</span><span class="cx">                                 84730D7C1248F0B300D3A9C9 /* FEDisplacementMap.cpp in Sources */,
</span><span class="cx">                                 4358E8801360A31700E4748C /* FEDropShadow.cpp in Sources */,
</span><ins>+                                CDF4B72B1E03C63E00E235A2 /* JSMediaKeysRequirement.cpp in Sources */,
</ins><span class="cx">                                 84730D7E1248F0B300D3A9C9 /* FEFlood.cpp in Sources */,
</span><span class="cx">                                 84801954108BAFB300CB2B1F /* FEGaussianBlur.cpp in Sources */,
</span><span class="cx">                                 84730D801248F0B300D3A9C9 /* FELighting.cpp in Sources */,
</span><span class="lines">@@ -30066,7 +30124,6 @@
</span><span class="cx">                                 2D9BF74A1DBFDDFF007A7D99 /* JSMediaKeySessionCustom.cpp in Sources */,
</span><span class="cx">                                 2D9BF7241DBFDAD0007A7D99 /* JSMediaKeyStatusMap.cpp in Sources */,
</span><span class="cx">                                 2D9BF7251DBFDAD3007A7D99 /* JSMediaKeySystemAccess.cpp in Sources */,
</span><del>-                                2D9BF74B1DBFDE02007A7D99 /* JSMediaKeySystemAccessCustom.cpp in Sources */,
</del><span class="cx">                                 2D9BF7261DBFDAD5007A7D99 /* JSMediaKeySystemConfiguration.cpp in Sources */,
</span><span class="cx">                                 2D9BF7271DBFDAD8007A7D99 /* JSMediaKeySystemMediaCapability.cpp in Sources */,
</span><span class="cx">                                 BC3C39B60C0D3D8D005F4D7A /* JSMediaList.cpp in Sources */,
</span><span class="lines">@@ -31388,6 +31445,7 @@
</span><span class="cx">                                 B2227A260D00BF220071B782 /* SVGGElement.cpp in Sources */,
</span><span class="cx">                                 B2A1F2AD0CEF0ABF00442F6A /* SVGGlyphElement.cpp in Sources */,
</span><span class="cx">                                 24D912BD13CA9A9700D21915 /* SVGGlyphRefElement.cpp in Sources */,
</span><ins>+                                CDF4B71D1E01E11A00E235A2 /* JSMediaKeySessionType.cpp in Sources */,
</ins><span class="cx">                                 B2227A290D00BF220071B782 /* SVGGradientElement.cpp in Sources */,
</span><span class="cx">                                 B2227AB50D00BF220071B782 /* SVGGraphicsElement.cpp in Sources */,
</span><span class="cx">                                 650FBF2A0D9AF047008FC292 /* SVGHKernElement.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMediaKeySystemAccessCustomcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/bindings/js/JSMediaKeySystemAccessCustom.cpp (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMediaKeySystemAccessCustom.cpp        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/bindings/js/JSMediaKeySystemAccessCustom.cpp        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1,47 +0,0 @@
</span><del>-/*
- * Copyright (C) 2016 Metrological Group B.V.
- * Copyright (C) 2016 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials provided
- *    with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include &quot;config.h&quot;
-
-#if ENABLE(ENCRYPTED_MEDIA)
-
-#include &quot;JSMediaKeySystemAccess.h&quot;
-
-#include &quot;NotImplemented.h&quot;
-
-namespace WebCore {
-
-JSC::JSValue JSMediaKeySystemAccess::getConfiguration(JSC::ExecState&amp;)
-{
-    notImplemented();
-    return JSC::jsUndefined();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(ENCRYPTED_MEDIA)
</del></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -1104,10 +1104,13 @@
</span><span class="cx"> 
</span><span class="cx">     my $result = &quot;&quot;;
</span><span class="cx">     $result .= &quot;#if ${conditionalString}\n\n&quot; if $conditionalString;
</span><del>-    $result .= &quot;template&lt;&gt; JSC::JSString* convertEnumerationToJS(JSC::ExecState&amp;, $className);\n\n&quot;;
-    $result .= &quot;template&lt;&gt; std::optional&lt;$className&gt; parseEnumeration&lt;$className&gt;(JSC::ExecState&amp;, JSC::JSValue);\n&quot;;
-    $result .= &quot;template&lt;&gt; $className convertEnumeration&lt;$className&gt;(JSC::ExecState&amp;, JSC::JSValue);\n&quot;;
-    $result .= &quot;template&lt;&gt; const char* expectedEnumerationValues&lt;$className&gt;();\n\n&quot;;
</del><ins>+
+    my $exportMacro = GetExportMacroForJSClass($enumeration);
+
+    $result .= &quot;template&lt;&gt; ${exportMacro}JSC::JSString* convertEnumerationToJS(JSC::ExecState&amp;, $className);\n\n&quot;;
+    $result .= &quot;template&lt;&gt; ${exportMacro}std::optional&lt;$className&gt; parseEnumeration&lt;$className&gt;(JSC::ExecState&amp;, JSC::JSValue);\n&quot;;
+    $result .= &quot;template&lt;&gt; ${exportMacro}$className convertEnumeration&lt;$className&gt;(JSC::ExecState&amp;, JSC::JSValue);\n&quot;;
+    $result .= &quot;template&lt;&gt; ${exportMacro}const char* expectedEnumerationValues&lt;$className&gt;();\n\n&quot;;
</ins><span class="cx">     $result .= &quot;#endif\n\n&quot; if $conditionalString;
</span><span class="cx">     
</span><span class="cx">     return $result;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/testing/Internals.cpp        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -162,6 +162,10 @@
</span><span class="cx"> #include &quot;LegacyMockCDM.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(ENCRYPTED_MEDIA)
+#include &quot;MockCDMFactory.h&quot;
+#endif
+
</ins><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx"> #include &quot;CaptionUserPreferences.h&quot;
</span><span class="cx"> #include &quot;PageGroup.h&quot;
</span><span class="lines">@@ -2609,6 +2613,14 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(ENCRYPTED_MEDIA)
+Ref&lt;MockCDMFactory&gt; Internals::registerMockCDM()
+{
+    return MockCDMFactory::create();
+}
+#endif
+
+
</ins><span class="cx"> String Internals::markerTextForListItem(Element&amp; element)
</span><span class="cx"> {
</span><span class="cx">     return WebCore::markerTextForListItem(&amp;element);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/testing/Internals.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> class MallocStatistics;
</span><span class="cx"> class MediaSession;
</span><span class="cx"> class MemoryInfo;
</span><ins>+class MockCDMFactory;
</ins><span class="cx"> class MockContentFilterSettings;
</span><span class="cx"> class MockPageOverlay;
</span><span class="cx"> class NodeList;
</span><span class="lines">@@ -372,6 +373,10 @@
</span><span class="cx">     void initializeMockCDM();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(ENCRYPTED_MEDIA)
+    Ref&lt;MockCDMFactory&gt; registerMockCDM();
+#endif
+
</ins><span class="cx"> #if ENABLE(SPEECH_SYNTHESIS)
</span><span class="cx">     void enableMockSpeechSynthesizer();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (209963 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2016-12-17 17:14:03 UTC (rev 209963)
+++ trunk/Source/WebCore/testing/Internals.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -378,6 +378,7 @@
</span><span class="cx">     [Conditional=VIDEO, MayThrowException] boolean mediaElementHasCharacteristic(HTMLMediaElement element, DOMString characteristic);
</span><span class="cx"> 
</span><span class="cx">     [Conditional=LEGACY_ENCRYPTED_MEDIA] void initializeMockCDM();
</span><ins>+    [Conditional=ENCRYPTED_MEDIA] MockCDMFactory registerMockCDM();
</ins><span class="cx"> 
</span><span class="cx">     [Conditional=SPEECH_SYNTHESIS] void enableMockSpeechSynthesizer();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMFactorycpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/testing/MockCDMFactory.cpp (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDMFactory.cpp                                (rev 0)
+++ trunk/Source/WebCore/testing/MockCDMFactory.cpp        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,124 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MockCDMFactory.h&quot;
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include &lt;wtf/NeverDestroyed.h&gt;
+
+namespace WebCore {
+
+MockCDMFactory::MockCDMFactory()
+    : m_weakPtrFactory(this)
+{
+    CDM::registerCDMFactory(*this);
+}
+
+MockCDMFactory::~MockCDMFactory()
+{
+    unregister();
+}
+
+void MockCDMFactory::unregister()
+{
+    if (m_registered) {
+        CDM::unregisterCDMFactory(*this);
+        m_registered = false;
+    }
+}
+
+bool MockCDMFactory::supportsKeySystem(const String&amp; keySystem)
+{
+    return equalIgnoringASCIICase(keySystem, &quot;org.webkit.mock&quot;);
+}
+
+std::unique_ptr&lt;CDMPrivate&gt; MockCDMFactory::createCDM(CDM&amp;)
+{
+    return std::make_unique&lt;MockCDM&gt;(m_weakPtrFactory.createWeakPtr());
+}
+
+MockCDM::MockCDM(WeakPtr&lt;MockCDMFactory&gt; factory)
+    : m_factory(WTFMove(factory))
+{
+}
+
+bool MockCDM::supportsInitDataType(const String&amp; initDataType)
+{
+    if (m_factory)
+        return m_factory-&gt;supportedDataTypes().contains(initDataType);
+    return false;
+}
+
+bool MockCDM::supportsConfiguration(const MediaKeySystemConfiguration&amp;)
+{
+    // NOTE: Implement;
+    return true;
+
+}
+
+bool MockCDM::supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;)
+{
+    // NOTE: Implement;
+    return true;
+}
+
+bool MockCDM::supportsSessionTypeWithConfiguration(MediaKeySessionType&amp;, const MediaKeySystemConfiguration&amp;)
+{
+    // NOTE: Implement;
+    return true;
+}
+
+bool MockCDM::supportsRobustness(const String&amp; robustness)
+{
+    if (m_factory)
+        return m_factory-&gt;supportedRobustness().contains(robustness);
+    return false;
+}
+
+MediaKeysRequirement MockCDM::distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;)
+{
+    if (m_factory)
+        return m_factory-&gt;distinctiveIdentifiersRequirement();
+    return MediaKeysRequirement::Optional;
+}
+
+MediaKeysRequirement MockCDM::persistentStateRequirement(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;)
+{
+    if (m_factory)
+        return m_factory-&gt;persistentStateRequirement();
+    return MediaKeysRequirement::Optional;
+}
+
+bool MockCDM::distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&amp;)
+{
+    // NOTE: Implement;
+    return true;
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMFactoryh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/testing/MockCDMFactory.h (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDMFactory.h                                (rev 0)
+++ trunk/Source/WebCore/testing/MockCDMFactory.h        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,90 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include &quot;CDM.h&quot;
+#include &quot;CDMPrivate.h&quot;
+#include &quot;MediaKeysRequirement.h&quot;
+#include &lt;wtf/RefCounted.h&gt;
+#include &lt;wtf/Vector.h&gt;
+#include &lt;wtf/WeakPtr.h&gt;
+
+namespace WebCore {
+
+class MockCDMFactory : public RefCounted&lt;MockCDMFactory&gt;, private CDMFactory {
+public:
+    static Ref&lt;MockCDMFactory&gt; create() { return adoptRef(*new MockCDMFactory); }
+    ~MockCDMFactory();
+
+    const Vector&lt;String&gt;&amp; supportedDataTypes() const { return m_supportedDataTypes; }
+    void setSupportedDataTypes(Vector&lt;String&gt;&amp;&amp; types) { m_supportedDataTypes = WTFMove(types); }
+
+    const Vector&lt;String&gt;&amp; supportedRobustness() const { return m_supportedRobustness; }
+    void setSupportedRobustness(Vector&lt;String&gt;&amp;&amp; robustness) { m_supportedRobustness = WTFMove(robustness); }
+
+    MediaKeysRequirement distinctiveIdentifiersRequirement() const { return m_distinctiveIdentifiersRequirement; }
+    void setDistinctiveIdentifiersRequirement(MediaKeysRequirement requirement) { m_distinctiveIdentifiersRequirement = requirement; }
+
+    MediaKeysRequirement persistentStateRequirement() const { return m_persistentStateRequirement; }
+    void setPersistentStateRequirement(MediaKeysRequirement requirement) { m_persistentStateRequirement = requirement; }
+
+    void unregister();
+
+private:
+    MockCDMFactory();
+    std::unique_ptr&lt;CDMPrivate&gt; createCDM(CDM&amp;) final;
+    bool supportsKeySystem(const String&amp;) final;
+
+    MediaKeysRequirement m_distinctiveIdentifiersRequirement { MediaKeysRequirement::Optional };
+    MediaKeysRequirement m_persistentStateRequirement { MediaKeysRequirement::Optional };
+    Vector&lt;String&gt; m_supportedDataTypes;
+    Vector&lt;String&gt; m_supportedRobustness;
+    bool m_registered { true };
+    WeakPtrFactory&lt;MockCDMFactory&gt; m_weakPtrFactory;
+};
+
+class MockCDM : public CDMPrivate {
+public:
+    MockCDM(WeakPtr&lt;MockCDMFactory&gt;);
+
+private:
+    bool supportsInitDataType(const String&amp;) final;
+    bool supportsConfiguration(const MediaKeySystemConfiguration&amp;) final;
+    bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;) final;
+    bool supportsSessionTypeWithConfiguration(MediaKeySessionType&amp;, const MediaKeySystemConfiguration&amp;) final;
+    bool supportsRobustness(const String&amp;) final;
+    MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;) final;
+    MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&amp;, const MediaKeysRestrictions&amp;) final;
+    bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&amp;) final;
+
+    WeakPtr&lt;MockCDMFactory&gt; m_factory;
+};
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMFactoryidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/testing/MockCDMFactory.idl (0 => 209964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDMFactory.idl                                (rev 0)
+++ trunk/Source/WebCore/testing/MockCDMFactory.idl        2016-12-17 17:18:54 UTC (rev 209964)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=ENCRYPTED_MEDIA,
+    NoInterfaceObject,
+    ExportMacro=WEBCORE_TESTSUPPORT_EXPORT,
+] interface MockCDMFactory {
+    attribute sequence&lt;DOMString&gt; supportedDataTypes;
+    attribute sequence&lt;DOMString&gt; supportedRobustness;
+    attribute MediaKeysRequirement distinctiveIdentifiersRequirement;
+    attribute MediaKeysRequirement persistentStateRequirement;
+
+    void unregister();
+};
+
</ins></span></pre>
</div>
</div>

</body>
</html>