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

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

<h3>Log Message</h3>
<pre>Adopt AVContentKeySession
https://bugs.webkit.org/show_bug.cgi?id=151221

Reviewed by Eric Carlson.

Adopt a new API for managing key state, AVContentKeySession. Because this necessitates a change
in both the initialization data returned by the needkey event, and passed into the createSession()
method, bump the protocol version number (to 3), and keep supporting the old key management API
for legacy content.

To do so, move most of the implementation of CDMPrivateMediaSourceAVFObjC into a new subclass,
CDMSessionAVStreamSession, and add a new subclass, CDMSessionAVContentKeySession, to support the
new API.

* platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.h:
(WebCore::CDMPrivateMediaSourceAVFObjC::CDMPrivateMediaSourceAVFObjC): Moved to implementation file.
* platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm:
(WebCore::validKeySystemRE): Support &quot;com.apple.fps.3_x&quot;.
(WebCore::CDMPrivateMediaSourceAVFObjC::~CDMPrivateMediaSourceAVFObjC): Invalidate all outstanding sessions.
(WebCore::CDMPrivateMediaSourceAVFObjC::supportsKeySystem): Only support &quot;com.apple.fps.3_x&quot; if the AVContentKeySession class is available.
(WebCore::CDMPrivateMediaSourceAVFObjC::createSession): Create an instance of CDMSessionAVContentKeySession if &quot;com.apple.fps.3_x&quot; is specified and AVContentKeySession is available.
(WebCore::CDMPrivateMediaSourceAVFObjC::invalidateSession): Remove session from the list of outstanding sessions.
(WebCore::CDMPrivateMediaSourceAVFObjC::supportsMIMEType): Deleted.
* platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h: Copied from Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h.
(WebCore::CDMSessionAVContentKeySession::hasContentKeySession): Simple accessor.
(WebCore::toCDMSessionAVContentKeySession): Safe casting.
* platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm: Added.
(-[CDMSessionAVContentKeySessionDelegate initWithParent:]): Simple constructor.
(-[CDMSessionAVContentKeySessionDelegate invalidate]): Remove reference to parent.
(-[CDMSessionAVContentKeySessionDelegate contentKeySession:willProvideKeyRequestInitializationDataForTrackID:]): Pass to parent.
(-[CDMSessionAVContentKeySessionDelegate contentKeySession:didProvideKeyRequestInitializationData:requestHandling:]): Ditto.
(-[CDMSessionAVContentKeySessionDelegate contentKeySessionContentProtectionSessionIdentifierDidChange:]): Ditto.
(WebCore::CDMSessionAVContentKeySession::CDMSessionAVContentKeySession): Create the delegate.
(WebCore::CDMSessionAVContentKeySession::~CDMSessionAVContentKeySession): Invalidate the delegate and remove all parsers.
(WebCore::CDMSessionAVContentKeySession::isAvailable): Return true if AVContentKeySession class is available.
(WebCore::CDMSessionAVContentKeySession::generateKeyRequest): Support &quot;keyrelease&quot; message, setting of the certificate, and creating key request object.
(WebCore::CDMSessionAVContentKeySession::releaseKeys): Retrieve keys from storage location.
(WebCore::isEqual): Compares a Uint8Array to a char*.
(WebCore::CDMSessionAVContentKeySession::update): Support &quot;acknowledged&quot; message, &quot;renew&quot; message, and key addition.
(WebCore::CDMSessionAVContentKeySession::addParser): Add the parser to the AVContentKeySession.
(WebCore::CDMSessionAVContentKeySession::removeParser): Remove parser from same.
(WebCore::CDMSessionAVContentKeySession::generateKeyReleaseMessage): Retrieve key release message from AVContentKeySession.
(WebCore::CDMSessionAVContentKeySession::didProvideContentKeyRequest): Simple setter.
(WebCore::CDMSessionAVContentKeySession::contentKeySession): Lazily create the AVContentKeySession.
* platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm:
(WebCore::CDMSessionAVFoundationObjC::CDMSessionAVFoundationObjC):
* platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.h: Copied from Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h.
(WebCore::toCDMSessionAVStreamSession):
* platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.mm: Copied from Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm.
(-[CDMSessionAVStreamSessionObserver initWithParent:]): Moved from CDMSessionMediaSourceAVFObjcObserver.
(-[CDMSessionAVStreamSessionObserver contentProtectionSessionIdentifierChanged:]): Ditto.
(WebCore::CDMSessionAVStreamSession::CDMSessionAVStreamSession): Ditto.
(WebCore::CDMSessionAVStreamSession::~CDMSessionAVStreamSession): Ditto.
(WebCore::CDMSessionAVStreamSession::generateKeyRequest): Ditto.
(WebCore::CDMSessionAVStreamSession::releaseKeys): Ditto.
(WebCore::isEqual): Ditto.
(WebCore::CDMSessionAVStreamSession::update): Ditto.
(WebCore::CDMSessionAVStreamSession::setStreamSession): Ditto.
(WebCore::CDMSessionAVStreamSession::addParser): Ditto.
(WebCore::CDMSessionAVStreamSession::removeParser): Ditto.
(WebCore::CDMSessionAVStreamSession::generateKeyReleaseMessage): Ditto.
* platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h:
(WebCore::CDMSessionMediaSourceAVFObjC::invalidateCDM): Clear the m_cdm.
(WebCore::toCDMSessionMediaSourceAVFObjC):
* platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm:
(WebCore::CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC):
(WebCore::CDMSessionMediaSourceAVFObjC::~CDMSessionMediaSourceAVFObjC): Instruct our CDM to invalidate their references to us.
(WebCore::CDMSessionMediaSourceAVFObjC::addSourceBuffer): Call addParser().
(WebCore::CDMSessionMediaSourceAVFObjC::removeSourceBuffer): Call removeParser().
(WebCore::CDMSessionMediaSourceAVFObjC::layerDidReceiveError): Deleted.
(WebCore::CDMSessionMediaSourceAVFObjC::rendererDidReceiveError): Deleted.

To give us a chance to create a CDMPrivate before we continue decoding media data, &quot;block&quot; further decoding
on the background thread by creating a semaphore and passing it to the main thread, to be triggered when
a CDM is created and attached to this source buffer.

* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]):
(WebCore::SourceBufferPrivateAVFObjC::~SourceBufferPrivateAVFObjC):
(WebCore::SourceBufferPrivateAVFObjC::willProvideContentKeyRequestInitializationDataForTrackID):
(WebCore::SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID):
(WebCore::SourceBufferPrivateAVFObjC::setCDMSession):
(-[WebAVStreamDataParserListener streamDataParserWillProvideContentKeyRequestInitializationData:forTrackID:]): Deleted.
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:

Drive-by fix: Only throw an error from keyRequestTimerFired() if the underlying call to
generateKeyRequest() returned an error, rather than just failed to create a message.

* Modules/encryptedmedia/MediaKeySession.cpp:
(WebCore::MediaKeySession::keyRequestTimerFired):

Drive-by fix: Pass the CDMSessionClient into CDM::createSession() so that it is immediately available
in the CDMSessionPrivate constructor, rather than setting the client immediately after construction.

* Modules/encryptedmedia/CDM.cpp:
(WebCore::CDM::createSession):
* Modules/encryptedmedia/CDM.h:
* Modules/encryptedmedia/CDMPrivate.h:
* Modules/encryptedmedia/CDMPrivateClearKey.cpp:
(WebCore::CDMPrivateClearKey::createSession):
* Modules/encryptedmedia/CDMPrivateClearKey.h:
* Modules/encryptedmedia/CDMPrivateMediaPlayer.cpp:
(WebCore::CDMPrivateMediaPlayer::createSession):
* Modules/encryptedmedia/CDMPrivateMediaPlayer.h:
* Modules/encryptedmedia/CDMSessionClearKey.cpp:
(WebCore::CDMSessionClearKey::CDMSessionClearKey):
* Modules/encryptedmedia/CDMSessionClearKey.h:
* Modules/encryptedmedia/MediaKeySession.cpp:
(WebCore::MediaKeySession::MediaKeySession):
* platform/graphics/CDMSession.h:
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::createSession):
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::createSession):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::createSession):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::cdmSession):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setCDMSession):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded): Deleted.
* testing/MockCDM.cpp:
(WebCore::MockCDM::createSession):
(WebCore::MockCDMSession::MockCDMSession):
* testing/MockCDM.h:

Add new files to the project:

* WebCore.xcodeproj/project.pbxproj:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</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="#trunkSourceWebCoreModulesencryptedmediaCDMPrivateClearKeycpp">trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMPrivateClearKeyh">trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMPrivateMediaPlayercpp">trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMPrivateMediaPlayerh">trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMSessionClearKeycpp">trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMSessionClearKeyh">trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySessioncpp">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsCDMSessionh">trunk/Source/WebCore/platform/graphics/CDMSession.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayercpp">trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayerh">trunk/Source/WebCore/platform/graphics/MediaPlayer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayerPrivateh">trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationCDMPrivateMediaSourceAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationCDMPrivateMediaSourceAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVFoundationObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVFoundationObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscacocoaPlatformCALayerCocoamm">trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMcpp">trunk/Source/WebCore/testing/MockCDM.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMh">trunk/Source/WebCore/testing/MockCDM.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVContentKeySessionh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVContentKeySessionmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVStreamSessionh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVStreamSessionmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/ChangeLog        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -1,3 +1,140 @@
</span><ins>+2015-12-01  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        Adopt AVContentKeySession
+        https://bugs.webkit.org/show_bug.cgi?id=151221
+
+        Reviewed by Eric Carlson.
+
+        Adopt a new API for managing key state, AVContentKeySession. Because this necessitates a change
+        in both the initialization data returned by the needkey event, and passed into the createSession()
+        method, bump the protocol version number (to 3), and keep supporting the old key management API
+        for legacy content.
+
+        To do so, move most of the implementation of CDMPrivateMediaSourceAVFObjC into a new subclass,
+        CDMSessionAVStreamSession, and add a new subclass, CDMSessionAVContentKeySession, to support the
+        new API.
+
+        * platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.h:
+        (WebCore::CDMPrivateMediaSourceAVFObjC::CDMPrivateMediaSourceAVFObjC): Moved to implementation file.
+        * platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm:
+        (WebCore::validKeySystemRE): Support &quot;com.apple.fps.3_x&quot;.
+        (WebCore::CDMPrivateMediaSourceAVFObjC::~CDMPrivateMediaSourceAVFObjC): Invalidate all outstanding sessions.
+        (WebCore::CDMPrivateMediaSourceAVFObjC::supportsKeySystem): Only support &quot;com.apple.fps.3_x&quot; if the AVContentKeySession class is available.
+        (WebCore::CDMPrivateMediaSourceAVFObjC::createSession): Create an instance of CDMSessionAVContentKeySession if &quot;com.apple.fps.3_x&quot; is specified and AVContentKeySession is available.
+        (WebCore::CDMPrivateMediaSourceAVFObjC::invalidateSession): Remove session from the list of outstanding sessions.
+        (WebCore::CDMPrivateMediaSourceAVFObjC::supportsMIMEType): Deleted.
+        * platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h: Copied from Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h.
+        (WebCore::CDMSessionAVContentKeySession::hasContentKeySession): Simple accessor.
+        (WebCore::toCDMSessionAVContentKeySession): Safe casting.
+        * platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm: Added.
+        (-[CDMSessionAVContentKeySessionDelegate initWithParent:]): Simple constructor.
+        (-[CDMSessionAVContentKeySessionDelegate invalidate]): Remove reference to parent.
+        (-[CDMSessionAVContentKeySessionDelegate contentKeySession:willProvideKeyRequestInitializationDataForTrackID:]): Pass to parent.
+        (-[CDMSessionAVContentKeySessionDelegate contentKeySession:didProvideKeyRequestInitializationData:requestHandling:]): Ditto.
+        (-[CDMSessionAVContentKeySessionDelegate contentKeySessionContentProtectionSessionIdentifierDidChange:]): Ditto.
+        (WebCore::CDMSessionAVContentKeySession::CDMSessionAVContentKeySession): Create the delegate.
+        (WebCore::CDMSessionAVContentKeySession::~CDMSessionAVContentKeySession): Invalidate the delegate and remove all parsers.
+        (WebCore::CDMSessionAVContentKeySession::isAvailable): Return true if AVContentKeySession class is available.
+        (WebCore::CDMSessionAVContentKeySession::generateKeyRequest): Support &quot;keyrelease&quot; message, setting of the certificate, and creating key request object. 
+        (WebCore::CDMSessionAVContentKeySession::releaseKeys): Retrieve keys from storage location.
+        (WebCore::isEqual): Compares a Uint8Array to a char*.
+        (WebCore::CDMSessionAVContentKeySession::update): Support &quot;acknowledged&quot; message, &quot;renew&quot; message, and key addition.
+        (WebCore::CDMSessionAVContentKeySession::addParser): Add the parser to the AVContentKeySession.
+        (WebCore::CDMSessionAVContentKeySession::removeParser): Remove parser from same.
+        (WebCore::CDMSessionAVContentKeySession::generateKeyReleaseMessage): Retrieve key release message from AVContentKeySession.
+        (WebCore::CDMSessionAVContentKeySession::didProvideContentKeyRequest): Simple setter.
+        (WebCore::CDMSessionAVContentKeySession::contentKeySession): Lazily create the AVContentKeySession.
+        * platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm:
+        (WebCore::CDMSessionAVFoundationObjC::CDMSessionAVFoundationObjC):
+        * platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.h: Copied from Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h.
+        (WebCore::toCDMSessionAVStreamSession):
+        * platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.mm: Copied from Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm.
+        (-[CDMSessionAVStreamSessionObserver initWithParent:]): Moved from CDMSessionMediaSourceAVFObjcObserver.
+        (-[CDMSessionAVStreamSessionObserver contentProtectionSessionIdentifierChanged:]): Ditto.
+        (WebCore::CDMSessionAVStreamSession::CDMSessionAVStreamSession): Ditto.
+        (WebCore::CDMSessionAVStreamSession::~CDMSessionAVStreamSession): Ditto.
+        (WebCore::CDMSessionAVStreamSession::generateKeyRequest): Ditto.
+        (WebCore::CDMSessionAVStreamSession::releaseKeys): Ditto.
+        (WebCore::isEqual): Ditto.
+        (WebCore::CDMSessionAVStreamSession::update): Ditto.
+        (WebCore::CDMSessionAVStreamSession::setStreamSession): Ditto.
+        (WebCore::CDMSessionAVStreamSession::addParser): Ditto.
+        (WebCore::CDMSessionAVStreamSession::removeParser): Ditto.
+        (WebCore::CDMSessionAVStreamSession::generateKeyReleaseMessage): Ditto.
+        * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h:
+        (WebCore::CDMSessionMediaSourceAVFObjC::invalidateCDM): Clear the m_cdm.
+        (WebCore::toCDMSessionMediaSourceAVFObjC):
+        * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm:
+        (WebCore::CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC):
+        (WebCore::CDMSessionMediaSourceAVFObjC::~CDMSessionMediaSourceAVFObjC): Instruct our CDM to invalidate their references to us.
+        (WebCore::CDMSessionMediaSourceAVFObjC::addSourceBuffer): Call addParser().
+        (WebCore::CDMSessionMediaSourceAVFObjC::removeSourceBuffer): Call removeParser().
+        (WebCore::CDMSessionMediaSourceAVFObjC::layerDidReceiveError): Deleted.
+        (WebCore::CDMSessionMediaSourceAVFObjC::rendererDidReceiveError): Deleted.
+        
+        To give us a chance to create a CDMPrivate before we continue decoding media data, &quot;block&quot; further decoding
+        on the background thread by creating a semaphore and passing it to the main thread, to be triggered when
+        a CDM is created and attached to this source buffer.
+
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+        (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]):
+        (WebCore::SourceBufferPrivateAVFObjC::~SourceBufferPrivateAVFObjC):
+        (WebCore::SourceBufferPrivateAVFObjC::willProvideContentKeyRequestInitializationDataForTrackID):
+        (WebCore::SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID):
+        (WebCore::SourceBufferPrivateAVFObjC::setCDMSession):
+        (-[WebAVStreamDataParserListener streamDataParserWillProvideContentKeyRequestInitializationData:forTrackID:]): Deleted.
+        * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+
+        Drive-by fix: Only throw an error from keyRequestTimerFired() if the underlying call to
+        generateKeyRequest() returned an error, rather than just failed to create a message.
+
+        * Modules/encryptedmedia/MediaKeySession.cpp:
+        (WebCore::MediaKeySession::keyRequestTimerFired):
+
+        Drive-by fix: Pass the CDMSessionClient into CDM::createSession() so that it is immediately available
+        in the CDMSessionPrivate constructor, rather than setting the client immediately after construction.
+
+        * Modules/encryptedmedia/CDM.cpp:
+        (WebCore::CDM::createSession):
+        * Modules/encryptedmedia/CDM.h:
+        * Modules/encryptedmedia/CDMPrivate.h:
+        * Modules/encryptedmedia/CDMPrivateClearKey.cpp:
+        (WebCore::CDMPrivateClearKey::createSession):
+        * Modules/encryptedmedia/CDMPrivateClearKey.h:
+        * Modules/encryptedmedia/CDMPrivateMediaPlayer.cpp:
+        (WebCore::CDMPrivateMediaPlayer::createSession):
+        * Modules/encryptedmedia/CDMPrivateMediaPlayer.h:
+        * Modules/encryptedmedia/CDMSessionClearKey.cpp:
+        (WebCore::CDMSessionClearKey::CDMSessionClearKey):
+        * Modules/encryptedmedia/CDMSessionClearKey.h:
+        * Modules/encryptedmedia/MediaKeySession.cpp:
+        (WebCore::MediaKeySession::MediaKeySession):
+        * platform/graphics/CDMSession.h:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::createSession):
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::createSession):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createSession):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::cdmSession):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setCDMSession):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded): Deleted.
+        * testing/MockCDM.cpp:
+        (WebCore::MockCDM::createSession):
+        (WebCore::MockCDMSession::MockCDMSession):
+        * testing/MockCDM.h:
+
+        Add new files to the project:
+
+        * WebCore.xcodeproj/project.pbxproj:
+
+
</ins><span class="cx"> 2015-12-04  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Modern IDB: storage/indexeddb/cursor-update.html fails.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -132,9 +132,9 @@
</span><span class="cx">     return m_private-&gt;supportsMIMEType(mimeType);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;CDMSession&gt; CDM::createSession()
</del><ins>+std::unique_ptr&lt;CDMSession&gt; CDM::createSession(CDMSessionClient* client)
</ins><span class="cx"> {
</span><del>-    std::unique_ptr&lt;CDMSession&gt; session = m_private-&gt;createSession();
</del><ins>+    std::unique_ptr&lt;CDMSession&gt; session = m_private-&gt;createSession(client);
</ins><span class="cx">     if (mediaPlayer())
</span><span class="cx">         mediaPlayer()-&gt;setCDMSession(session.get());
</span><span class="cx">     return session;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx">     ~CDM();
</span><span class="cx"> 
</span><span class="cx">     bool supportsMIMEType(const String&amp;) const;
</span><del>-    std::unique_ptr&lt;CDMSession&gt; createSession();
</del><ins>+    std::unique_ptr&lt;CDMSession&gt; createSession(CDMSessionClient*);
</ins><span class="cx"> 
</span><span class="cx">     const String&amp; keySystem() const { return m_keySystem; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class CDMSession;
</span><ins>+class CDMSessionClient;
</ins><span class="cx"> 
</span><span class="cx"> class CDMPrivateInterface {
</span><span class="cx"> public:
</span><span class="lines">@@ -41,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx">     virtual bool supportsMIMEType(const String&amp;) = 0;
</span><span class="cx"> 
</span><del>-    virtual std::unique_ptr&lt;CDMSession&gt; createSession() = 0;
</del><ins>+    virtual std::unique_ptr&lt;CDMSession&gt; createSession(CDMSessionClient*) = 0;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMPrivateClearKeycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -59,9 +59,9 @@
</span><span class="cx">     return MediaPlayer::supportsKeySystem(m_cdm-&gt;keySystem(), mimeType);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;CDMSession&gt; CDMPrivateClearKey::createSession()
</del><ins>+std::unique_ptr&lt;CDMSession&gt; CDMPrivateClearKey::createSession(CDMSessionClient* client)
</ins><span class="cx"> {
</span><del>-    return std::make_unique&lt;CDMSessionClearKey&gt;();
</del><ins>+    return std::make_unique&lt;CDMSessionClearKey&gt;(client);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMPrivateClearKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateClearKey.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">     static bool supportsKeySystemAndMimeType(const String&amp; keySystem, const String&amp; mimeType);
</span><span class="cx"> 
</span><span class="cx">     virtual bool supportsMIMEType(const String&amp; mimeType) override;
</span><del>-    virtual std::unique_ptr&lt;CDMSession&gt; createSession() override;
</del><ins>+    virtual std::unique_ptr&lt;CDMSession&gt; createSession(CDMSessionClient*) override;
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     CDM* m_cdm;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMPrivateMediaPlayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -55,13 +55,13 @@
</span><span class="cx">     return MediaPlayer::supportsKeySystem(m_cdm-&gt;keySystem(), mimeType);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;CDMSession&gt; CDMPrivateMediaPlayer::createSession()
</del><ins>+std::unique_ptr&lt;CDMSession&gt; CDMPrivateMediaPlayer::createSession(CDMSessionClient* client)
</ins><span class="cx"> {
</span><span class="cx">     MediaPlayer* mediaPlayer = m_cdm-&gt;mediaPlayer();
</span><span class="cx">     if (!mediaPlayer)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    return mediaPlayer-&gt;createSession(m_cdm-&gt;keySystem());
</del><ins>+    return mediaPlayer-&gt;createSession(m_cdm-&gt;keySystem(), client);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMPrivateMediaPlayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivateMediaPlayer.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">     virtual ~CDMPrivateMediaPlayer() { }
</span><span class="cx"> 
</span><span class="cx">     virtual bool supportsMIMEType(const String&amp; mimeType) override;
</span><del>-    virtual std::unique_ptr&lt;CDMSession&gt; createSession() override;
</del><ins>+    virtual std::unique_ptr&lt;CDMSession&gt; createSession(CDMSessionClient*) override;
</ins><span class="cx"> 
</span><span class="cx">     CDM* cdm() const { return m_cdm; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMSessionClearKeycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -59,8 +59,9 @@
</span><span class="cx">     return *vm.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CDMSessionClearKey::CDMSessionClearKey()
-    : m_sessionId(createCanonicalUUIDString())
</del><ins>+CDMSessionClearKey::CDMSessionClearKey(CDMSessionClient* client)
+    : m_client(client)
+    , m_sessionId(createCanonicalUUIDString())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMSessionClearKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMSessionClearKey.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> class CDMSessionClearKey : public CDMSession {
</span><span class="cx"> public:
</span><del>-    CDMSessionClearKey();
</del><ins>+    CDMSessionClearKey(CDMSessionClient*);
</ins><span class="cx">     virtual ~CDMSessionClearKey();
</span><span class="cx"> 
</span><span class="cx">     // CDMSessionPrivate
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -52,11 +52,10 @@
</span><span class="cx">     , m_keys(keys)
</span><span class="cx">     , m_keySystem(keySystem)
</span><span class="cx">     , m_asyncEventQueue(*this)
</span><del>-    , m_session(keys-&gt;cdm()-&gt;createSession())
</del><ins>+    , m_session(keys-&gt;cdm()-&gt;createSession(this))
</ins><span class="cx">     , m_keyRequestTimer(*this, &amp;MediaKeySession::keyRequestTimerFired)
</span><span class="cx">     , m_addKeyTimer(*this, &amp;MediaKeySession::addKeyTimerFired)
</span><span class="cx"> {
</span><del>-    m_session-&gt;setClient(this);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaKeySession::~MediaKeySession()
</span><span class="lines">@@ -119,7 +118,7 @@
</span><span class="cx">         RefPtr&lt;Uint8Array&gt; keyRequest = m_session-&gt;generateKeyRequest(request.mimeType, request.initData.get(), destinationURL, errorCode, systemCode);
</span><span class="cx"> 
</span><span class="cx">         // Otherwise [if a request is not successfully generated]:
</span><del>-        if (!keyRequest) {
</del><ins>+        if (errorCode) {
</ins><span class="cx">             // 3.1. Create a new MediaKeyError object with the following attributes:
</span><span class="cx">             //      code = the appropriate MediaKeyError code
</span><span class="cx">             //      systemCode = a Key System-specific value, if provided, and 0 otherwise
</span><span class="lines">@@ -134,7 +133,8 @@
</span><span class="cx">         //    The event is of type MediaKeyMessageEvent and has:
</span><span class="cx">         //    message = key request
</span><span class="cx">         //    destinationURL = destinationURL
</span><del>-        sendMessage(keyRequest.get(), destinationURL);
</del><ins>+        if (keyRequest)
+            sendMessage(keyRequest.get(), destinationURL);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -6055,10 +6055,13 @@
</span><span class="cx">                 CDDC1E7A18A952F30027A9D4 /* MediaSourcePrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDC1E7918A952F30027A9D4 /* MediaSourcePrivateClient.h */; };
</span><span class="cx">                 CDDD571518B57A8200A94FCB /* CDMSession.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE02E918B3DFC700CF7FF1 /* CDMSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CDDE02ED18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDDE02EB18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm */; };
</span><del>-                CDDE02F018B5651300CF7FF1 /* CDMSessionMediaSourceAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDDE02EF18B5651200CF7FF1 /* CDMSessionMediaSourceAVFObjC.mm */; };
</del><ins>+                CDDE02F018B5651300CF7FF1 /* CDMSessionAVStreamSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDDE02EF18B5651200CF7FF1 /* CDMSessionAVStreamSession.mm */; };
</ins><span class="cx">                 CDE3A85417F5FCE600C5BE20 /* AudioTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */; };
</span><span class="cx">                 CDE3A85717F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */; };
</span><span class="cx">                 CDE3A85817F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */; };
</span><ins>+                CDE595951BF16DF300A1CBE8 /* CDMSessionAVContentKeySession.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDE595931BF166AD00A1CBE8 /* CDMSessionAVContentKeySession.mm */; };
+                CDE595971BF26E2100A1CBE8 /* CDMSessionMediaSourceAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE595961BF26E2100A1CBE8 /* CDMSessionMediaSourceAVFObjC.h */; };
+                CDE5959D1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDE5959C1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm */; };
</ins><span class="cx">                 CDE7FC44181904B1002BBB77 /* OrderIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */; };
</span><span class="cx">                 CDE7FC45181904B1002BBB77 /* OrderIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE7FC43181904B1002BBB77 /* OrderIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CDE83DB1183C44060031EAA3 /* VideoPlaybackQuality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE83DAF183C44060031EAA3 /* VideoPlaybackQuality.cpp */; };
</span><span class="lines">@@ -13909,11 +13912,15 @@
</span><span class="cx">                 CDDE02E918B3DFC700CF7FF1 /* CDMSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDMSession.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDDE02EA18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMSessionAVFoundationObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDDE02EB18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDMSessionAVFoundationObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                CDDE02EE18B564FA00CF7FF1 /* CDMSessionMediaSourceAVFObjC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDMSessionMediaSourceAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
-                CDDE02EF18B5651200CF7FF1 /* CDMSessionMediaSourceAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDMSessionMediaSourceAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><ins>+                CDDE02EE18B564FA00CF7FF1 /* CDMSessionAVStreamSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDMSessionAVStreamSession.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDDE02EF18B5651200CF7FF1 /* CDMSessionAVStreamSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDMSessionAVStreamSession.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioTrackPrivateAVF.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioTrackPrivateAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioTrackPrivateAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                CDE595931BF166AD00A1CBE8 /* CDMSessionAVContentKeySession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDMSessionAVContentKeySession.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE595941BF166D100A1CBE8 /* CDMSessionAVContentKeySession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMSessionAVContentKeySession.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE595961BF26E2100A1CBE8 /* CDMSessionMediaSourceAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMSessionMediaSourceAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                CDE5959C1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDMSessionMediaSourceAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 CDE6560E17CA6E7600526BA7 /* mediaControlsApple.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = mediaControlsApple.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OrderIterator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CDE7FC43181904B1002BBB77 /* OrderIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrderIterator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -22795,10 +22802,14 @@
</span><span class="cx">                                 CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */,
</span><span class="cx">                                 CD54A760180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.cpp */,
</span><span class="cx">                                 CD54A761180F9F7000B076C9 /* AudioTrackPrivateMediaSourceAVFObjC.h */,
</span><ins>+                                CDE595941BF166D100A1CBE8 /* CDMSessionAVContentKeySession.h */,
+                                CDE595931BF166AD00A1CBE8 /* CDMSessionAVContentKeySession.mm */,
</ins><span class="cx">                                 CDDE02EA18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.h */,
</span><span class="cx">                                 CDDE02EB18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm */,
</span><del>-                                CDDE02EE18B564FA00CF7FF1 /* CDMSessionMediaSourceAVFObjC.h */,
-                                CDDE02EF18B5651200CF7FF1 /* CDMSessionMediaSourceAVFObjC.mm */,
</del><ins>+                                CDDE02EE18B564FA00CF7FF1 /* CDMSessionAVStreamSession.h */,
+                                CDDE02EF18B5651200CF7FF1 /* CDMSessionAVStreamSession.mm */,
+                                CDE595961BF26E2100A1CBE8 /* CDMSessionMediaSourceAVFObjC.h */,
+                                CDE5959C1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm */,
</ins><span class="cx">                                 07AA6B69166D019500D45671 /* InbandTextTrackPrivateAVFObjC.h */,
</span><span class="cx">                                 07AA6B6A166D019500D45671 /* InbandTextTrackPrivateAVFObjC.mm */,
</span><span class="cx">                                 07367DDD172CA67F00D861B9 /* InbandTextTrackPrivateLegacyAVFObjC.h */,
</span><span class="lines">@@ -27906,6 +27917,7 @@
</span><span class="cx">                                 FD3160AF12B026F700C1A359 /* VectorMath.h in Headers */,
</span><span class="cx">                                 BCA257151293C010007A263D /* VerticalPositionCache.h in Headers */,
</span><span class="cx">                                 CDE83DB2183C44060031EAA3 /* VideoPlaybackQuality.h in Headers */,
</span><ins>+                                CDE595971BF26E2100A1CBE8 /* CDMSessionMediaSourceAVFObjC.h in Headers */,
</ins><span class="cx">                                 BE88E0DF1715D2A200658D98 /* VideoTrack.h in Headers */,
</span><span class="cx">                                 BE88E0E21715D2A200658D98 /* VideoTrackList.h in Headers */,
</span><span class="cx">                                 CD8B5A46180DFF4E008B8E65 /* VideoTrackMediaSource.h in Headers */,
</span><span class="lines">@@ -28611,7 +28623,7 @@
</span><span class="cx">                                 CD318622199F1E2A0030A0F7 /* CDMPrivateMediaSourceAVFObjC.mm in Sources */,
</span><span class="cx">                                 CDDE02ED18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm in Sources */,
</span><span class="cx">                                 CDE8B5F01A69778B00B4B66A /* CDMSessionClearKey.cpp in Sources */,
</span><del>-                                CDDE02F018B5651300CF7FF1 /* CDMSessionMediaSourceAVFObjC.mm in Sources */,
</del><ins>+                                CDDE02F018B5651300CF7FF1 /* CDMSessionAVStreamSession.mm in Sources */,
</ins><span class="cx">                                 5F2DBBE9178E3C8100141486 /* CertificateInfoMac.mm in Sources */,
</span><span class="cx">                                 E1A8E56617552B2A007488E7 /* CFURLExtras.cpp in Sources */,
</span><span class="cx">                                 97BC69DC1505F076001B74AC /* ChangeVersionWrapper.cpp in Sources */,
</span><span class="lines">@@ -28954,6 +28966,7 @@
</span><span class="cx">                                 85DF2EEE0AA387CB00AD64C5 /* DOMHTMLElement.mm in Sources */,
</span><span class="cx">                                 85C050BB0AD84F5E005532E7 /* DOMHTMLEmbedElement.mm in Sources */,
</span><span class="cx">                                 85BA4CE00AA6861B0088052D /* DOMHTMLFieldSetElement.mm in Sources */,
</span><ins>+                                CDE5959D1BF2757100A1CBE8 /* CDMSessionMediaSourceAVFObjC.mm in Sources */,
</ins><span class="cx">                                 85ECBEF00AA7626900544F0B /* DOMHTMLFontElement.mm in Sources */,
</span><span class="cx">                                 85DF2C5D0AA341F600AD64C5 /* DOMHTMLFormElement.mm in Sources */,
</span><span class="cx">                                 85DF81960AA77E4B00486AD7 /* DOMHTMLFrameElement.mm in Sources */,
</span><span class="lines">@@ -29048,6 +29061,7 @@
</span><span class="cx">                                 CD9DE18117AAD6A400EA386D /* DOMURLMediaSource.cpp in Sources */,
</span><span class="cx">                                 15FCC9FC1B4DF7F200E72326 /* DOMURLMediaStream.cpp in Sources */,
</span><span class="cx">                                 BC1A37BF097C715F0019F3D8 /* DOMUtility.mm in Sources */,
</span><ins>+                                CDE595951BF16DF300A1CBE8 /* CDMSessionAVContentKeySession.mm in Sources */,
</ins><span class="cx">                                 15C770A5100D41CD005BA267 /* DOMValidityState.mm in Sources */,
</span><span class="cx">                                 31C0FF4A0E4CEFDD007D6FE5 /* DOMWebKitAnimationEvent.mm in Sources */,
</span><span class="cx">                                 3106037A143281CD00ABF4BA /* DOMWebKitCSSFilterValue.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsCDMSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/CDMSession.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/CDMSession.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/CDMSession.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -58,7 +58,8 @@
</span><span class="cx">     CDMSessionTypeUnknown,
</span><span class="cx">     CDMSessionTypeClearKey,
</span><span class="cx">     CDMSessionTypeAVFoundationObjC,
</span><del>-    CDMSessionTypeMediaSourceAVFObjC,
</del><ins>+    CDMSessionTypeAVStreamSession,
+    CDMSessionTypeAVContentKeySession,
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class CDMSession {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -532,9 +532,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><del>-std::unique_ptr&lt;CDMSession&gt; MediaPlayer::createSession(const String&amp; keySystem)
</del><ins>+std::unique_ptr&lt;CDMSession&gt; MediaPlayer::createSession(const String&amp; keySystem, CDMSessionClient* client)
</ins><span class="cx"> {
</span><del>-    return m_private-&gt;createSession(keySystem);
</del><ins>+    return m_private-&gt;createSession(keySystem, client);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayer::setCDMSession(CDMSession* session)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -116,6 +116,7 @@
</span><span class="cx"> 
</span><span class="cx"> extern const PlatformMedia NoPlatformMedia;
</span><span class="cx"> 
</span><ins>+class CDMSessionClient;
</ins><span class="cx"> class CachedResourceLoader;
</span><span class="cx"> class ContentType;
</span><span class="cx"> class GraphicsContext;
</span><span class="lines">@@ -359,7 +360,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><del>-    std::unique_ptr&lt;CDMSession&gt; createSession(const String&amp; keySystem);
</del><ins>+    std::unique_ptr&lt;CDMSession&gt; createSession(const String&amp; keySystem, CDMSessionClient*);
</ins><span class="cx">     void setCDMSession(CDMSession*);
</span><span class="cx">     void keyAdded();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayerPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -230,7 +230,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><del>-    virtual std::unique_ptr&lt;CDMSession&gt; createSession(const String&amp;) { return nullptr; }
</del><ins>+    virtual std::unique_ptr&lt;CDMSession&gt; createSession(const String&amp;, CDMSessionClient*) { return nullptr; }
</ins><span class="cx">     virtual void setCDMSession(CDMSession*) { }
</span><span class="cx">     virtual void keyAdded() { }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationCDMPrivateMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -29,28 +29,33 @@
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CDMPrivate.h&quot;
</span><ins>+#include &lt;wtf/Vector.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class CDM;
</span><ins>+class CDMSessionMediaSourceAVFObjC;
</ins><span class="cx"> 
</span><span class="cx"> class CDMPrivateMediaSourceAVFObjC : public CDMPrivateInterface {
</span><span class="cx"> public:
</span><span class="cx">     explicit CDMPrivateMediaSourceAVFObjC(CDM* cdm)
</span><span class="cx">         : m_cdm(cdm)
</span><span class="cx">     { }
</span><del>-    virtual ~CDMPrivateMediaSourceAVFObjC() { }
</del><ins>+    virtual ~CDMPrivateMediaSourceAVFObjC();
</ins><span class="cx"> 
</span><span class="cx">     static bool supportsKeySystem(const String&amp;);
</span><span class="cx">     static bool supportsKeySystemAndMimeType(const String&amp; keySystem, const String&amp; mimeType);
</span><span class="cx"> 
</span><span class="cx">     virtual bool supportsMIMEType(const String&amp; mimeType) override;
</span><del>-    virtual std::unique_ptr&lt;CDMSession&gt; createSession() override;
</del><ins>+    virtual std::unique_ptr&lt;CDMSession&gt; createSession(CDMSessionClient*) override;
</ins><span class="cx"> 
</span><span class="cx">     CDM* cdm() const { return m_cdm; }
</span><span class="cx"> 
</span><ins>+    void invalidateSession(CDMSessionMediaSourceAVFObjC*);
+
</ins><span class="cx"> protected:
</span><span class="cx">     CDM* m_cdm;
</span><ins>+    Vector&lt;CDMSessionMediaSourceAVFObjC*&gt; m_sessions;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationCDMPrivateMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMPrivateMediaSourceAVFObjC.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -29,7 +29,8 @@
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</span><span class="cx"> 
</span><span class="cx"> #import &quot;CDM.h&quot;
</span><del>-#import &quot;CDMSessionMediaSourceAVFObjC.h&quot;
</del><ins>+#import &quot;CDMSessionAVContentKeySession.h&quot;
+#import &quot;CDMSessionAVStreamSession.h&quot;
</ins><span class="cx"> #import &quot;ContentType.h&quot;
</span><span class="cx"> #import &quot;ExceptionCode.h&quot;
</span><span class="cx"> #import &quot;MediaPlayerPrivateMediaSourceAVFObjC.h&quot;
</span><span class="lines">@@ -43,10 +44,16 @@
</span><span class="cx"> 
</span><span class="cx"> static RegularExpression&amp; validKeySystemRE()
</span><span class="cx"> {
</span><del>-    static NeverDestroyed&lt;RegularExpression&gt; keySystemRE(&quot;^com\\.apple\\.fps\\.2_\\d+(?:,\\d+)*$&quot;, TextCaseInsensitive);
</del><ins>+    static NeverDestroyed&lt;RegularExpression&gt; keySystemRE(&quot;^com\\.apple\\.fps\\.[23]_\\d+(?:,\\d+)*$&quot;, TextCaseInsensitive);
</ins><span class="cx">     return keySystemRE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CDMPrivateMediaSourceAVFObjC::~CDMPrivateMediaSourceAVFObjC()
+{
+    for (auto&amp; session : m_sessions)
+        session-&gt;invalidateCDM();
+}
+
</ins><span class="cx"> bool CDMPrivateMediaSourceAVFObjC::supportsKeySystem(const String&amp; keySystem)
</span><span class="cx"> {
</span><span class="cx">     if (!wkQueryDecoderAvailability())
</span><span class="lines">@@ -55,6 +62,9 @@
</span><span class="cx">     if (!keySystem.isEmpty() &amp;&amp; validKeySystemRE().match(keySystem) &lt; 0)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    if (keySystem.substring(14, 1).toInt() == 3 &amp;&amp; !CDMSessionAVContentKeySession::isAvailable())
+        return false;
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -89,7 +99,7 @@
</span><span class="cx">     return MediaPlayerPrivateMediaSourceAVFObjC::supportsType(parameters) != MediaPlayer::IsNotSupported;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;CDMSession&gt; CDMPrivateMediaSourceAVFObjC::createSession()
</del><ins>+std::unique_ptr&lt;CDMSession&gt; CDMPrivateMediaSourceAVFObjC::createSession(CDMSessionClient* client)
</ins><span class="cx"> {
</span><span class="cx">     String keySystem = m_cdm-&gt;keySystem();
</span><span class="cx">     ASSERT(validKeySystemRE().match(keySystem) &gt;= 0);
</span><span class="lines">@@ -101,9 +111,22 @@
</span><span class="cx">     for (auto&amp; protocolVersionString : protocolVersionsStrings)
</span><span class="cx">         protocolVersions.append(protocolVersionString.toInt());
</span><span class="cx"> 
</span><del>-    return std::make_unique&lt;CDMSessionMediaSourceAVFObjC&gt;(protocolVersions);
</del><ins>+    std::unique_ptr&lt;CDMSessionMediaSourceAVFObjC&gt; session;
+    if (keySystem.substring(14, 1).toInt() == 3 &amp;&amp; CDMSessionAVContentKeySession::isAvailable())
+        session = std::make_unique&lt;CDMSessionAVContentKeySession&gt;(protocolVersions, *this, client);
+    else
+        session = std::make_unique&lt;CDMSessionAVStreamSession&gt;(protocolVersions, *this, client);
+
+    m_sessions.append(session.get());
+    return WTF::move(session);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CDMPrivateMediaSourceAVFObjC::invalidateSession(CDMSessionMediaSourceAVFObjC* session)
+{
+    ASSERT(m_sessions.contains(session));
+    m_sessions.removeAll(session);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif // ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVContentKeySessionhfromrev193471trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h (from rev 193471, trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h) (0 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef CDMSessionAVContentKeySession_h
+#define CDMSessionAVContentKeySession_h
+
+#include &quot;CDMSessionMediaSourceAVFObjC.h&quot;
+#include &quot;SourceBufferPrivateAVFObjC.h&quot;
+#include &lt;wtf/RetainPtr.h&gt;
+
+#if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
+
+OBJC_CLASS AVContentKeyRequest;
+OBJC_CLASS AVContentKeySession;
+OBJC_CLASS CDMSessionAVContentKeySessionDelegate;
+
+namespace WebCore {
+
+class CDMPrivateMediaSourceAVFObjC;
+
+class CDMSessionAVContentKeySession : public CDMSessionMediaSourceAVFObjC {
+public:
+    CDMSessionAVContentKeySession(const Vector&lt;int&gt;&amp; protocolVersions, CDMPrivateMediaSourceAVFObjC&amp;, CDMSessionClient*);
+    virtual ~CDMSessionAVContentKeySession();
+
+    static bool isAvailable();
+
+    // CDMSession
+    virtual CDMSessionType type() override { return CDMSessionTypeAVContentKeySession; }
+    virtual RefPtr&lt;Uint8Array&gt; generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode) override;
+    virtual void releaseKeys() override;
+    virtual bool update(Uint8Array* key, RefPtr&lt;Uint8Array&gt;&amp; nextMessage, unsigned short&amp; errorCode, unsigned long&amp; systemCode) override;
+
+    // CDMSessionMediaSourceAVFObjC
+    void addParser(AVStreamDataParser *) override;
+    void removeParser(AVStreamDataParser *) override;
+
+    void didProvideContentKeyRequest(AVContentKeyRequest *);
+
+protected:
+    PassRefPtr&lt;Uint8Array&gt; generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode);
+
+    bool hasContentKeySession() const { return m_contentKeySession; }
+    AVContentKeySession* contentKeySession();
+
+    RetainPtr&lt;AVContentKeySession&gt; m_contentKeySession;
+    RetainPtr&lt;CDMSessionAVContentKeySessionDelegate&gt; m_contentKeySessionDelegate;
+    RetainPtr&lt;AVContentKeyRequest&gt; m_keyRequest;
+    RefPtr&lt;Uint8Array&gt; m_initData;
+    RetainPtr&lt;NSData&gt; m_expiredSession;
+    Vector&lt;int&gt; m_protocolVersions;
+    int32_t m_protectedTrackID { 1 };
+    enum { Normal, KeyRelease } m_mode;
+};
+
+inline CDMSessionAVContentKeySession* toCDMSessionAVContentKeySession(CDMSession* session)
+{
+    if (!session || session-&gt;type() != CDMSessionTypeAVContentKeySession)
+        return nullptr;
+    return static_cast&lt;CDMSessionAVContentKeySession*&gt;(session);
+}
+
+}
+
+#endif
+
+#endif // CDMSessionAVContentKeySession_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVContentKeySessionmm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm (0 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -0,0 +1,357 @@
</span><ins>+/*
+ * Copyright (C) 2015 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.
+ */
+
+#import &quot;config.h&quot;
+#import &quot;CDMSessionAVContentKeySession.h&quot;
+
+#if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
+
+#import &quot;CDM.h&quot;
+#import &quot;CDMPrivateMediaSourceAVFObjC.h&quot;
+#import &quot;ExceptionCode.h&quot;
+#import &quot;FileSystem.h&quot;
+#import &quot;Logging.h&quot;
+#import &quot;MediaPlayer.h&quot;
+#import &quot;SoftLinking.h&quot;
+#import &quot;SourceBufferPrivateAVFObjC.h&quot;
+#import &quot;UUID.h&quot;
+#import &lt;AVFoundation/AVError.h&gt;
+#import &lt;CoreMedia/CMBase.h&gt;
+#import &lt;cstdlib&gt;
+#import &lt;objc/objc-runtime.h&gt;
+#import &lt;runtime/TypedArrayInlines.h&gt;
+#import &lt;wtf/NeverDestroyed.h&gt;
+
+SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
+SOFT_LINK_CLASS(AVFoundation, AVStreamDataParser);
+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVContentKeySession);
+SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVContentKeyRequestProtocolVersionsKey, NSString *)
+
+@interface AVContentKeySession : NSObject
+- (instancetype)initWithStorageDirectoryAtURL:(NSURL *)storageURL;
+@property (assign) id delegate;
+- (void)addStreamDataParser:(AVStreamDataParser *)streamDataParser;
+- (void)removeStreamDataParser:(AVStreamDataParser *)streamDataParser;
+@property (readonly) NSArray *streamDataParsers;
+- (void)expire;
+@property (readonly) NSData *contentProtectionSessionIdentifier;
+- (void)processContentKeyRequestInitializationData:(NSData *)initializationData options:(NSDictionary *)options;
++ (NSArray *)pendingExpiredSessionReportsWithAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
++ (void)removePendingExpiredSessionReports:(NSArray *)expiredSessionReports withAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
+@end
+
+typedef NS_ENUM(NSInteger, AVContentKeyRequestStatus) {
+    AVContentKeySessionStatusNoKey,
+    AVContentKeySessionStatusRequestingKey,
+    AVContentKeySessionStatusKeyPresent,
+    AVContentKeySessionStatusExpired,
+    AVContentKeySessionStatusFailed
+};
+
+@interface AVContentKeyRequest : NSObject
+@property (readonly) AVContentKeyRequestStatus status;
+@property (readonly) NSError *error;
+@property (readonly) NSData *initializationData;
+- (NSData *)contentKeyRequestDataForApp:(NSData *)appIdentifier contentIdentifier:(NSData *)contentIdentifier options:(NSDictionary *)options error:(NSError **)outError;
+- (void)processContentKeyResponseData:(NSData *)contentKeyResponseData;
+- (void)processContentKeyResponseError:(NSError *)error;
+- (void)renewExpiringContentKeyResponseData;
+@end
+
+@interface CDMSessionAVContentKeySessionDelegate : NSObject {
+    WebCore::CDMSessionAVContentKeySession *m_parent;
+}
+- (void)invalidate;
+@end
+
+@implementation CDMSessionAVContentKeySessionDelegate
+- (id)initWithParent:(WebCore::CDMSessionAVContentKeySession *)parent
+{
+    if ((self = [super init]))
+        m_parent = parent;
+    return self;
+}
+
+
+- (void)invalidate
+{
+    m_parent = nullptr;
+}
+
+- (void)contentKeySession:(AVContentKeySession *)session didProvideContentKeyRequest:(AVContentKeyRequest *)keyRequest
+{
+    UNUSED_PARAM(session);
+
+    if (m_parent)
+        m_parent-&gt;didProvideContentKeyRequest(keyRequest);
+}
+
+- (void)contentKeySessionContentProtectionSessionIdentifierDidChange:(AVContentKeySession *)session
+{
+    if (!m_parent)
+        return;
+
+    NSData* identifier = [session contentProtectionSessionIdentifier];
+    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:NSUTF8StringEncoding]) : nil;
+    m_parent-&gt;setSessionId(sessionIdentifierString.get());
+}
+@end
+
+static const NSString *PlaybackSessionIdKey = @&quot;PlaybackSessionID&quot;;
+
+namespace WebCore {
+
+CDMSessionAVContentKeySession::CDMSessionAVContentKeySession(const Vector&lt;int&gt;&amp; protocolVersions, CDMPrivateMediaSourceAVFObjC&amp; cdm, CDMSessionClient* client)
+    : CDMSessionMediaSourceAVFObjC(cdm, client)
+    , m_contentKeySessionDelegate(adoptNS([[CDMSessionAVContentKeySessionDelegate alloc] initWithParent:this]))
+    , m_protocolVersions(protocolVersions)
+    , m_mode(Normal)
+{
+}
+
+CDMSessionAVContentKeySession::~CDMSessionAVContentKeySession()
+{
+    [m_contentKeySessionDelegate invalidate];
+
+    for (auto&amp; sourceBuffer : m_sourceBuffers)
+        removeParser(sourceBuffer-&gt;parser());
+}
+
+bool CDMSessionAVContentKeySession::isAvailable()
+{
+    return getAVContentKeySessionClass();
+}
+
+RefPtr&lt;Uint8Array&gt; CDMSessionAVContentKeySession::generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
+{
+    UNUSED_PARAM(mimeType);
+    UNUSED_PARAM(destinationURL);
+    ASSERT(initData);
+
+    LOG(Media, &quot;CDMSessionAVContentKeySession::generateKeyRequest(%p)&quot;, this);
+
+    errorCode = MediaPlayer::NoError;
+    systemCode = 0;
+
+    m_initData = initData;
+
+    if (equalIgnoringCase(mimeType, &quot;keyrelease&quot;)) {
+        m_mode = KeyRelease;
+        return generateKeyReleaseMessage(errorCode, systemCode);
+    }
+
+    if (!m_certificate) {
+        String certificateString(ASCIILiteral(&quot;certificate&quot;));
+        RefPtr&lt;Uint8Array&gt; array = Uint8Array::create(certificateString.length());
+        for (unsigned i = 0, length = certificateString.length(); i &lt; length; ++i)
+            array-&gt;set(i, certificateString[i]);
+        return array;
+    }
+
+    if (!m_keyRequest) {
+        NSData* nsInitData = [NSData dataWithBytes:m_initData-&gt;data() length:m_initData-&gt;length()];
+        [contentKeySession() processContentKeyRequestInitializationData:nsInitData options:nil];
+    }
+
+    return nullptr;
+}
+
+void CDMSessionAVContentKeySession::releaseKeys()
+{
+    if (hasContentKeySession()) {
+        m_stopped = true;
+        for (auto&amp; sourceBuffer : m_sourceBuffers)
+            sourceBuffer-&gt;flush();
+
+        LOG(Media, &quot;CDMSessionAVContentKeySession::releaseKeys(%p) - expiring stream session&quot;, this);
+        [contentKeySession() expire];
+
+        if (!m_certificate)
+            return;
+
+        if (![getAVContentKeySessionClass() respondsToSelector:@selector(pendingExpiredSessionReportsWithAppIdentifier:storageDirectoryAtURL:)])
+            return;
+
+        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+        NSArray* expiredSessions = [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
+        for (NSData* expiredSessionData in expiredSessions) {
+            NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr];
+            NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey];
+            if (![playbackSessionIdValue isKindOfClass:[NSString class]])
+                continue;
+
+            if (m_sessionId == String(playbackSessionIdValue)) {
+                LOG(Media, &quot;CDMSessionAVContentKeySession::releaseKeys(%p) - found session, sending expiration message&quot;);
+                m_expiredSession = expiredSessionData;
+                m_client-&gt;sendMessage(Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]).get(), emptyString());
+                break;
+            }
+        }
+    }
+}
+
+static bool isEqual(Uint8Array* data, const char* literal)
+{
+    ASSERT(data);
+    ASSERT(literal);
+    unsigned length = data-&gt;length();
+
+    for (unsigned i = 0; i &lt; length; ++i) {
+        if (!literal[i])
+            return false;
+
+        if (data-&gt;item(i) != static_cast&lt;uint8_t&gt;(literal[i]))
+            return false;
+    }
+    return !literal[length];
+}
+
+bool CDMSessionAVContentKeySession::update(Uint8Array* key, RefPtr&lt;Uint8Array&gt;&amp; nextMessage, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
+{
+    UNUSED_PARAM(nextMessage);
+
+    bool shouldGenerateKeyRequest = !m_certificate || isEqual(key, &quot;renew&quot;);
+    if (!m_certificate) {
+        LOG(Media, &quot;CDMSessionAVContentKeySession::update(%p) - certificate data&quot;, this);
+
+        m_certificate = key;
+    }
+
+    if (isEqual(key, &quot;acknowledged&quot;)) {
+        LOG(Media, &quot;CDMSessionAVContentKeySession::update(%p) - acknowleding secure stop message&quot;, this);
+
+        if (!m_expiredSession) {
+            errorCode = MediaPlayer::InvalidPlayerState;
+            return false;
+        }
+
+        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+
+        if ([getAVContentKeySessionClass() respondsToSelector:@selector(removePendingExpiredSessionReports:withAppIdentifier:storageDirectoryAtURL:)])
+            [getAVContentKeySessionClass() removePendingExpiredSessionReports:@[m_expiredSession.get()] withAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
+        m_expiredSession = nullptr;
+        return true;
+    }
+
+    if (m_mode == KeyRelease)
+        return false;
+
+    if (!m_keyRequest) {
+        NSData* nsInitData = [NSData dataWithBytes:m_initData-&gt;data() length:m_initData-&gt;length()];
+        [contentKeySession() processContentKeyRequestInitializationData:nsInitData options:nil];
+    }
+
+    if (shouldGenerateKeyRequest) {
+        ASSERT(m_keyRequest);
+        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+
+        RetainPtr&lt;NSData&gt; initData = adoptNS([[NSData alloc] initWithBytes:m_initData-&gt;data() length:m_initData-&gt;length()]);
+
+        RetainPtr&lt;NSDictionary&gt; options;
+        if (!m_protocolVersions.isEmpty() &amp;&amp; canLoadAVContentKeyRequestProtocolVersionsKey()) {
+            RetainPtr&lt;NSMutableArray&gt; protocolVersionsOption = adoptNS([[NSMutableArray alloc] init]);
+            for (auto&amp; version : m_protocolVersions) {
+                if (!version)
+                    continue;
+                [protocolVersionsOption addObject:@(version)];
+            }
+
+            options = @{ getAVContentKeyRequestProtocolVersionsKey(): protocolVersionsOption.get() };
+        }
+
+        errorCode = MediaPlayer::NoError;
+        systemCode = 0;
+        NSData* requestData = [m_keyRequest contentKeyRequestDataForApp:certificateData.get() contentIdentifier:initData.get() options:options.get() error:nil];
+        nextMessage = Uint8Array::create(static_cast&lt;const uint8_t*&gt;([requestData bytes]), [requestData length]);
+
+        return false;
+    }
+
+    LOG(Media, &quot;CDMSessionAVContentKeySession::update(%p) - key data&quot;, this);
+    errorCode = MediaPlayer::NoError;
+    systemCode = 0;
+    RetainPtr&lt;NSData&gt; keyData = adoptNS([[NSData alloc] initWithBytes:key-&gt;data() length:key-&gt;length()]);
+    [m_keyRequest processContentKeyResponseData:keyData.get()];
+
+    return true;
+}
+
+void CDMSessionAVContentKeySession::addParser(AVStreamDataParser* parser)
+{
+    [contentKeySession() addStreamDataParser:parser];
+}
+
+void CDMSessionAVContentKeySession::removeParser(AVStreamDataParser* parser)
+{
+    [contentKeySession() removeStreamDataParser:parser];
+}
+
+PassRefPtr&lt;Uint8Array&gt; CDMSessionAVContentKeySession::generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode)
+{
+    ASSERT(m_mode == KeyRelease);
+    m_certificate = m_initData;
+    RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+
+    if (![getAVContentKeySessionClass() respondsToSelector:@selector(pendingExpiredSessionReportsWithAppIdentifier:storageDirectoryAtURL:)]) {
+        errorCode = MediaPlayer::KeySystemNotSupported;
+        systemCode = '!mor';
+        return nullptr;
+    }
+
+    NSArray* expiredSessions = [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
+    if (![expiredSessions count]) {
+        LOG(Media, &quot;CDMSessionAVContentKeySession::generateKeyReleaseMessage(%p) - no expired sessions found&quot;, this);
+
+        errorCode = MediaPlayer::KeySystemNotSupported;
+        systemCode = '!mor';
+        return nullptr;
+    }
+
+    LOG(Media, &quot;CDMSessionAVContentKeySession::generateKeyReleaseMessage(%p) - found %d expired sessions&quot;, this, [expiredSessions count]);
+
+    errorCode = 0;
+    systemCode = 0;
+    m_expiredSession = [expiredSessions firstObject];
+    return Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]);
+}
+
+void CDMSessionAVContentKeySession::didProvideContentKeyRequest(AVContentKeyRequest *keyRequest)
+{
+    m_keyRequest = keyRequest;
+}
+
+AVContentKeySession* CDMSessionAVContentKeySession::contentKeySession()
+{
+    if (!m_contentKeySession) {
+        m_contentKeySession = adoptNS([[getAVContentKeySessionClass() alloc] initWithStorageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]]);
+        m_contentKeySession.get().delegate = m_contentKeySessionDelegate.get();
+    }
+
+    return m_contentKeySession.get();
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVFoundationObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> class CDMSessionAVFoundationObjC : public CDMSession {
</span><span class="cx"> public:
</span><del>-    CDMSessionAVFoundationObjC(MediaPlayerPrivateAVFoundationObjC* parent);
</del><ins>+    CDMSessionAVFoundationObjC(MediaPlayerPrivateAVFoundationObjC* parent, CDMSessionClient*);
</ins><span class="cx">     virtual ~CDMSessionAVFoundationObjC() { }
</span><span class="cx"> 
</span><span class="cx">     virtual CDMSessionType type() override { return CDMSessionTypeAVFoundationObjC; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVFoundationObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -46,9 +46,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-CDMSessionAVFoundationObjC::CDMSessionAVFoundationObjC(MediaPlayerPrivateAVFoundationObjC* parent)
</del><ins>+CDMSessionAVFoundationObjC::CDMSessionAVFoundationObjC(MediaPlayerPrivateAVFoundationObjC* parent, CDMSessionClient* client)
</ins><span class="cx">     : m_parent(parent)
</span><del>-    , m_client(nullptr)
</del><ins>+    , m_client(client)
</ins><span class="cx">     , m_sessionId(createCanonicalUUIDString())
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVStreamSessionhfromrev193471trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.h (from rev 193471, trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h) (0 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.h                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef CDMSessionAVStreamSession_h
+#define CDMSessionAVStreamSession_h
+
+#include &quot;CDMSessionMediaSourceAVFObjC.h&quot;
+#include &quot;SourceBufferPrivateAVFObjC.h&quot;
+#include &lt;wtf/RetainPtr.h&gt;
+#include &lt;wtf/WeakPtr.h&gt;
+
+#if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
+
+OBJC_CLASS AVStreamSession;
+OBJC_CLASS CDMSessionAVStreamSessionObserver;
+
+namespace WebCore {
+
+class CDMPrivateMediaSourceAVFObjC;
+
+class CDMSessionAVStreamSession : public CDMSessionMediaSourceAVFObjC {
+public:
+    CDMSessionAVStreamSession(const Vector&lt;int&gt;&amp; protocolVersions, CDMPrivateMediaSourceAVFObjC&amp;, CDMSessionClient*);
+    virtual ~CDMSessionAVStreamSession();
+
+    // CDMSession
+    virtual CDMSessionType type() override { return CDMSessionTypeAVStreamSession; }
+    virtual RefPtr&lt;Uint8Array&gt; generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode) override;
+    virtual void releaseKeys() override;
+    virtual bool update(Uint8Array*, RefPtr&lt;Uint8Array&gt;&amp; nextMessage, unsigned short&amp; errorCode, unsigned long&amp; systemCode) override;
+
+    // CDMSessionMediaSourceAVFObjC
+    void addParser(AVStreamDataParser*) override;
+    void removeParser(AVStreamDataParser*) override;
+
+    void setStreamSession(AVStreamSession*);
+
+protected:
+    PassRefPtr&lt;Uint8Array&gt; generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode);
+
+    WeakPtrFactory&lt;CDMSessionAVStreamSession&gt; m_weakPtrFactory;
+    RetainPtr&lt;AVStreamSession&gt; m_streamSession;
+    RefPtr&lt;Uint8Array&gt; m_initData;
+    RefPtr&lt;Uint8Array&gt; m_certificate;
+    RetainPtr&lt;NSData&gt; m_expiredSession;
+    RetainPtr&lt;CDMSessionAVStreamSessionObserver&gt; m_dataParserObserver;
+    Vector&lt;int&gt; m_protocolVersions;
+    enum { Normal, KeyRelease } m_mode;
+};
+
+inline CDMSessionAVStreamSession* toCDMSessionAVStreamSession(CDMSession* session)
+{
+    if (!session || session-&gt;type() != CDMSessionTypeAVStreamSession)
+        return nullptr;
+    return static_cast&lt;CDMSessionAVStreamSession*&gt;(session);
+}
+
+}
+
+#endif
+
+#endif // CDMSessionAVStreamSession_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionAVStreamSessionmmfromrev193471trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCmm"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.mm (from rev 193471, trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm) (0 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.mm                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVStreamSession.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -0,0 +1,338 @@
</span><ins>+/*
+ * Copyright (C) 2015 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.
+ */
+
+#import &quot;config.h&quot;
+#import &quot;CDMSessionAVStreamSession.h&quot;
+
+#if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
+
+#import &quot;CDM.h&quot;
+#import &quot;CDMPrivateMediaSourceAVFObjC.h&quot;
+#import &quot;ExceptionCode.h&quot;
+#import &quot;FileSystem.h&quot;
+#import &quot;Logging.h&quot;
+#import &quot;MediaPlayer.h&quot;
+#import &quot;SoftLinking.h&quot;
+#import &quot;SourceBufferPrivateAVFObjC.h&quot;
+#import &quot;UUID.h&quot;
+#import &lt;AVFoundation/AVError.h&gt;
+#import &lt;CoreMedia/CMBase.h&gt;
+#import &lt;cstdlib&gt;
+#import &lt;objc/objc-runtime.h&gt;
+#import &lt;runtime/TypedArrayInlines.h&gt;
+#import &lt;wtf/NeverDestroyed.h&gt;
+
+SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
+SOFT_LINK_CLASS(AVFoundation, AVStreamDataParser);
+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamSession);
+SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVStreamDataParserContentKeyRequestProtocolVersionsKey, NSString *)
+SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVStreamSessionContentProtectionSessionIdentifierChangedNotification, NSString *)
+
+@interface AVStreamDataParser : NSObject
+- (void)processContentKeyResponseData:(NSData *)contentKeyResponseData forTrackID:(CMPersistentTrackID)trackID;
+- (void)processContentKeyResponseError:(NSError *)error forTrackID:(CMPersistentTrackID)trackID;
+- (void)renewExpiringContentKeyResponseDataForTrackID:(CMPersistentTrackID)trackID;
+- (NSData *)streamingContentKeyRequestDataForApp:(NSData *)appIdentifier contentIdentifier:(NSData *)contentIdentifier trackID:(CMPersistentTrackID)trackID options:(NSDictionary *)options error:(NSError **)outError;
+@end
+
+@interface AVStreamSession : NSObject
+- (void)addStreamDataParser:(AVStreamDataParser *)streamDataParser;
+- (void)removeStreamDataParser:(AVStreamDataParser *)streamDataParser;
+- (void)expire;
+- (NSData *)contentProtectionSessionIdentifier;
++ (NSArray *)pendingExpiredSessionReportsWithAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
++ (void)removePendingExpiredSessionReports:(NSArray *)expiredSessionReports withAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
+@end
+
+@interface CDMSessionAVStreamSessionObserver : NSObject {
+    WebCore::CDMSessionAVStreamSession *m_parent;
+}
+@end
+
+@implementation CDMSessionAVStreamSessionObserver
+- (id)initWithParent:(WebCore::CDMSessionAVStreamSession *)parent
+{
+    if ((self = [super init]))
+        m_parent = parent;
+    return self;
+}
+
+- (void)contentProtectionSessionIdentifierChanged:(NSNotification *)notification
+{
+    AVStreamSession* streamSession = (AVStreamSession*)[notification object];
+
+    NSData* identifier = [streamSession contentProtectionSessionIdentifier];
+    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:NSUTF8StringEncoding]) : nil;
+
+    if (m_parent)
+        m_parent-&gt;setSessionId(sessionIdentifierString.get());
+}
+@end
+
+static const NSString *PlaybackSessionIdKey = @&quot;PlaybackSessionID&quot;;
+
+namespace WebCore {
+
+CDMSessionAVStreamSession::CDMSessionAVStreamSession(const Vector&lt;int&gt;&amp; protocolVersions, CDMPrivateMediaSourceAVFObjC&amp; cdm, CDMSessionClient* client)
+    : CDMSessionMediaSourceAVFObjC(cdm, client)
+    , m_weakPtrFactory(this)
+    , m_dataParserObserver(adoptNS([[CDMSessionAVStreamSessionObserver alloc] initWithParent:this]))
+    , m_protocolVersions(protocolVersions)
+    , m_mode(Normal)
+{
+}
+
+CDMSessionAVStreamSession::~CDMSessionAVStreamSession()
+{
+    setStreamSession(nullptr);
+
+    for (auto&amp; sourceBuffer : m_sourceBuffers)
+        removeParser(sourceBuffer-&gt;parser());
+}
+
+RefPtr&lt;Uint8Array&gt; CDMSessionAVStreamSession::generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
+{
+    UNUSED_PARAM(mimeType);
+    UNUSED_PARAM(destinationURL);
+    ASSERT(initData);
+
+    LOG(Media, &quot;CDMSessionAVStreamSession::generateKeyRequest(%p)&quot;, this);
+
+    errorCode = MediaPlayer::NoError;
+    systemCode = 0;
+
+    m_initData = initData;
+
+    if (equalIgnoringCase(mimeType, &quot;keyrelease&quot;)) {
+        m_mode = KeyRelease;
+        return generateKeyReleaseMessage(errorCode, systemCode);
+    }
+
+    String certificateString(ASCIILiteral(&quot;certificate&quot;));
+    RefPtr&lt;Uint8Array&gt; array = Uint8Array::create(certificateString.length());
+    for (unsigned i = 0, length = certificateString.length(); i &lt; length; ++i)
+        array-&gt;set(i, certificateString[i]);
+    return array;
+}
+
+void CDMSessionAVStreamSession::releaseKeys()
+{
+    if (m_streamSession) {
+        m_stopped = true;
+        for (auto&amp; sourceBuffer : m_sourceBuffers)
+            sourceBuffer-&gt;flush();
+
+        LOG(Media, &quot;CDMSessionAVStreamSession::releaseKeys(%p) - expiring stream session&quot;, this);
+        [m_streamSession expire];
+
+        if (!m_certificate)
+            return;
+
+        if (![getAVStreamSessionClass() respondsToSelector:@selector(pendingExpiredSessionReportsWithAppIdentifier:storageDirectoryAtURL:)])
+            return;
+
+        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+        NSArray* expiredSessions = [getAVStreamSessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
+        for (NSData* expiredSessionData in expiredSessions) {
+            NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr];
+            NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey];
+            if (![playbackSessionIdValue isKindOfClass:[NSString class]])
+                continue;
+
+            if (m_sessionId == String(playbackSessionIdValue)) {
+                LOG(Media, &quot;CDMSessionAVStreamSession::releaseKeys(%p) - found session, sending expiration message&quot;);
+                m_expiredSession = expiredSessionData;
+                m_client-&gt;sendMessage(Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]).get(), emptyString());
+                break;
+            }
+        }
+    }
+}
+
+static bool isEqual(Uint8Array* data, const char* literal)
+{
+    ASSERT(data);
+    ASSERT(literal);
+    unsigned length = data-&gt;length();
+
+    for (unsigned i = 0; i &lt; length; ++i) {
+        if (!literal[i])
+            return false;
+
+        if (data-&gt;item(i) != static_cast&lt;uint8_t&gt;(literal[i]))
+            return false;
+    }
+    return !literal[length];
+}
+
+bool CDMSessionAVStreamSession::update(Uint8Array* key, RefPtr&lt;Uint8Array&gt;&amp; nextMessage, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
+{
+    bool shouldGenerateKeyRequest = !m_certificate || isEqual(key, &quot;renew&quot;);
+    if (!m_certificate) {
+        LOG(Media, &quot;CDMSessionAVStreamSession::update(%p) - certificate data&quot;, this);
+
+        m_certificate = key;
+    }
+
+    if (isEqual(key, &quot;acknowledged&quot;)) {
+        LOG(Media, &quot;CDMSessionAVStreamSession::update(%p) - acknowleding secure stop message&quot;, this);
+
+        if (!m_expiredSession) {
+            errorCode = MediaPlayer::InvalidPlayerState;
+            return false;
+        }
+
+        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+
+        if ([getAVStreamSessionClass() respondsToSelector:@selector(removePendingExpiredSessionReports:withAppIdentifier:storageDirectoryAtURL:)])
+            [getAVStreamSessionClass() removePendingExpiredSessionReports:@[m_expiredSession.get()] withAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
+        m_expiredSession = nullptr;
+        return true;
+    }
+
+    if (m_mode == KeyRelease)
+        return false;
+
+    RefPtr&lt;SourceBufferPrivateAVFObjC&gt; protectedSourceBuffer;
+    for (auto&amp; sourceBuffer : m_sourceBuffers) {
+        if (sourceBuffer-&gt;protectedTrackID() != -1) {
+            protectedSourceBuffer = sourceBuffer;
+            break;
+        }
+    }
+
+    if (shouldGenerateKeyRequest) {
+        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+
+        if (m_sourceBuffers.isEmpty())
+            return true;
+
+        if (!protectedSourceBuffer)
+            return true;
+
+        RetainPtr&lt;NSData&gt; initData = adoptNS([[NSData alloc] initWithBytes:m_initData-&gt;data() length:m_initData-&gt;length()]);
+
+        RetainPtr&lt;NSDictionary&gt; options;
+        if (!m_protocolVersions.isEmpty() &amp;&amp; canLoadAVStreamDataParserContentKeyRequestProtocolVersionsKey()) {
+            RetainPtr&lt;NSMutableArray&gt; protocolVersionsOption = adoptNS([[NSMutableArray alloc] init]);
+            for (auto&amp; version : m_protocolVersions) {
+                if (!version)
+                    continue;
+                [protocolVersionsOption addObject:@(version)];
+            }
+
+            options = @{ getAVStreamDataParserContentKeyRequestProtocolVersionsKey(): protocolVersionsOption.get() };
+        }
+
+        NSError* error = nil;
+        RetainPtr&lt;NSData&gt; request = [protectedSourceBuffer-&gt;parser() streamingContentKeyRequestDataForApp:certificateData.get() contentIdentifier:initData.get() trackID:protectedSourceBuffer-&gt;protectedTrackID() options:options.get() error:&amp;error];
+
+        if (![protectedSourceBuffer-&gt;parser() respondsToSelector:@selector(contentProtectionSessionIdentifier)])
+            m_sessionId = createCanonicalUUIDString();
+
+        if (error) {
+            LOG(Media, &quot;CDMSessionAVStreamSession::update(%p) - error:%@&quot;, this, [error description]);
+            errorCode = MediaPlayer::InvalidPlayerState;
+            systemCode = std::abs(systemCodeForError(error));
+            return false;
+        }
+
+        nextMessage = Uint8Array::create([request length]);
+        [request getBytes:nextMessage-&gt;data() length:nextMessage-&gt;length()];
+        return false;
+    }
+
+    ASSERT(!m_sourceBuffers.isEmpty());
+    LOG(Media, &quot;CDMSessionAVStreamSession::update(%p) - key data&quot;, this);
+    errorCode = MediaPlayer::NoError;
+    systemCode = 0;
+    RetainPtr&lt;NSData&gt; keyData = adoptNS([[NSData alloc] initWithBytes:key-&gt;data() length:key-&gt;length()]);
+    [protectedSourceBuffer-&gt;parser() processContentKeyResponseData:keyData.get() forTrackID:protectedSourceBuffer-&gt;protectedTrackID()];
+
+    return true;
+}
+
+void CDMSessionAVStreamSession::setStreamSession(AVStreamSession *streamSession)
+{
+    if (m_streamSession &amp;&amp; canLoadAVStreamSessionContentProtectionSessionIdentifierChangedNotification())
+        [[NSNotificationCenter defaultCenter] removeObserver:m_dataParserObserver.get() name:getAVStreamSessionContentProtectionSessionIdentifierChangedNotification() object:m_streamSession.get()];
+
+    m_streamSession = streamSession;
+
+    if (!m_streamSession)
+        return;
+
+    if (canLoadAVStreamSessionContentProtectionSessionIdentifierChangedNotification())
+        [[NSNotificationCenter defaultCenter] addObserver:m_dataParserObserver.get() selector:@selector(contentProtectionSessionIdentifierChanged:) name:getAVStreamSessionContentProtectionSessionIdentifierChangedNotification() object:m_streamSession.get()];
+
+    NSData* identifier = [streamSession contentProtectionSessionIdentifier];
+    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:(NSUTF8StringEncoding)]) : nil;
+    setSessionId(sessionIdentifierString.get());
+}
+
+void CDMSessionAVStreamSession::addParser(AVStreamDataParser* parser)
+{
+    if (m_streamSession)
+        [m_streamSession addStreamDataParser:parser];
+}
+
+void CDMSessionAVStreamSession::removeParser(AVStreamDataParser* parser)
+{
+    if (m_streamSession)
+        [m_streamSession removeStreamDataParser:parser];
+}
+
+PassRefPtr&lt;Uint8Array&gt; CDMSessionAVStreamSession::generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode)
+{
+    ASSERT(m_mode == KeyRelease);
+    m_certificate = m_initData;
+    RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
+
+    if (![getAVStreamSessionClass() respondsToSelector:@selector(pendingExpiredSessionReportsWithAppIdentifier:storageDirectoryAtURL:)]) {
+        errorCode = MediaPlayer::KeySystemNotSupported;
+        systemCode = '!mor';
+        return nullptr;
+    }
+
+    NSArray* expiredSessions = [getAVStreamSessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
+    if (![expiredSessions count]) {
+        LOG(Media, &quot;CDMSessionAVStreamSession::generateKeyReleaseMessage(%p) - no expired sessions found&quot;, this);
+
+        errorCode = MediaPlayer::KeySystemNotSupported;
+        systemCode = '!mor';
+        return nullptr;
+    }
+
+    LOG(Media, &quot;CDMSessionAVStreamSession::generateKeyReleaseMessage(%p) - found %d expired sessions&quot;, this, [expiredSessions count]);
+
+    errorCode = 0;
+    systemCode = 0;
+    m_expiredSession = [expiredSessions firstObject];
+    return Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]);
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,62 +29,60 @@
</span><span class="cx"> #include &quot;CDMSession.h&quot;
</span><span class="cx"> #include &quot;SourceBufferPrivateAVFObjC.h&quot;
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><ins>+#include &lt;wtf/WeakPtr.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</span><span class="cx"> 
</span><del>-OBJC_CLASS AVStreamSession;
-OBJC_CLASS CDMSessionMediaSourceAVFObjCObserver;
</del><ins>+OBJC_CLASS AVStreamDataParser;
+OBJC_CLASS NSError;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class CDMPrivateMediaSourceAVFObjC;
+
</ins><span class="cx"> class CDMSessionMediaSourceAVFObjC : public CDMSession, public SourceBufferPrivateAVFObjCErrorClient {
</span><span class="cx"> public:
</span><del>-    CDMSessionMediaSourceAVFObjC(const Vector&lt;int&gt;&amp; protocolVersions);
</del><ins>+    CDMSessionMediaSourceAVFObjC(CDMPrivateMediaSourceAVFObjC&amp;, CDMSessionClient*);
</ins><span class="cx">     virtual ~CDMSessionMediaSourceAVFObjC();
</span><span class="cx"> 
</span><del>-    virtual CDMSessionType type() override { return CDMSessionTypeMediaSourceAVFObjC; }
</del><ins>+    virtual void addParser(AVStreamDataParser*) = 0;
+    virtual void removeParser(AVStreamDataParser*) = 0;
+
+    // CDMSession
</ins><span class="cx">     virtual void setClient(CDMSessionClient* client) override { m_client = client; }
</span><span class="cx">     virtual const String&amp; sessionId() const override { return m_sessionId; }
</span><del>-    virtual RefPtr&lt;Uint8Array&gt; generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode) override;
-    virtual void releaseKeys() override;
-    virtual bool update(Uint8Array*, RefPtr&lt;Uint8Array&gt;&amp; nextMessage, unsigned short&amp; errorCode, unsigned long&amp; systemCode) override;
</del><span class="cx"> 
</span><ins>+    // SourceBufferPrivateAVFObjCErrorClient
</ins><span class="cx">     virtual void layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *, bool&amp; shouldIgnore) override;
</span><span class="cx">     virtual void rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError *, bool&amp; shouldIgnore) override;
</span><span class="cx"> 
</span><del>-    void setStreamSession(AVStreamSession *);
-
</del><span class="cx">     void addSourceBuffer(SourceBufferPrivateAVFObjC*);
</span><span class="cx">     void removeSourceBuffer(SourceBufferPrivateAVFObjC*);
</span><del>-
</del><span class="cx">     void setSessionId(const String&amp; sessionId) { m_sessionId = sessionId; }
</span><span class="cx"> 
</span><ins>+    void invalidateCDM() { m_cdm = nullptr; }
+
</ins><span class="cx"> protected:
</span><ins>+    static long systemCodeForError(NSError *);
</ins><span class="cx">     String storagePath() const;
</span><del>-    PassRefPtr&lt;Uint8Array&gt; generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode);
</del><span class="cx"> 
</span><ins>+    CDMPrivateMediaSourceAVFObjC* m_cdm;
+    CDMSessionClient* m_client { nullptr };
</ins><span class="cx">     Vector&lt;RefPtr&lt;SourceBufferPrivateAVFObjC&gt;&gt; m_sourceBuffers;
</span><del>-    CDMSessionClient* m_client;
-    RetainPtr&lt;AVStreamSession&gt; m_streamSession;
-    RefPtr&lt;Uint8Array&gt; m_initData;
</del><span class="cx">     RefPtr&lt;Uint8Array&gt; m_certificate;
</span><del>-    RetainPtr&lt;NSData&gt; m_expiredSession;
-    RetainPtr&lt;CDMSessionMediaSourceAVFObjCObserver&gt; m_dataParserObserver;
-    Vector&lt;int&gt; m_protocolVersions;
</del><span class="cx">     String m_sessionId;
</span><del>-    enum { Normal, KeyRelease } m_mode;
-    bool m_stopped = { false };
</del><ins>+    bool m_stopped { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline CDMSessionMediaSourceAVFObjC* toCDMSessionMediaSourceAVFObjC(CDMSession* session)
</span><span class="cx"> {
</span><del>-    if (!session || session-&gt;type() != CDMSessionTypeMediaSourceAVFObjC)
</del><ins>+    if (!session || (session-&gt;type() != CDMSessionTypeAVStreamSession &amp;&amp; session-&gt;type() != CDMSessionTypeAVContentKeySession))
</ins><span class="cx">         return nullptr;
</span><span class="cx">     return static_cast&lt;CDMSessionMediaSourceAVFObjC*&gt;(session);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+#endif // ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</ins><span class="cx"> 
</span><span class="cx"> #endif // CDMSessionMediaSourceAVFObjC_h
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,267 +28,25 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</span><span class="cx"> 
</span><del>-#import &quot;CDM.h&quot;
-#import &quot;CDMSession.h&quot;
-#import &quot;ExceptionCode.h&quot;
</del><ins>+#import &quot;CDMPrivateMediaSourceAVFObjC.h&quot;
</ins><span class="cx"> #import &quot;FileSystem.h&quot;
</span><del>-#import &quot;Logging.h&quot;
-#import &quot;MediaPlayer.h&quot;
-#import &quot;SourceBufferPrivateAVFObjC.h&quot;
-#import &quot;SoftLinking.h&quot;
-#import &quot;UUID.h&quot;
</del><span class="cx"> #import &lt;AVFoundation/AVError.h&gt;
</span><del>-#import &lt;CoreMedia/CMBase.h&gt;
</del><span class="cx"> #import &lt;cstdlib&gt;
</span><del>-#import &lt;objc/objc-runtime.h&gt;
-#import &lt;wtf/NeverDestroyed.h&gt;
-#import &lt;runtime/TypedArrayInlines.h&gt;
</del><span class="cx"> 
</span><del>-SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
-SOFT_LINK_CLASS(AVFoundation, AVStreamDataParser);
-SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamSession);
-SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVStreamDataParserContentKeyRequestProtocolVersionsKey, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVStreamSessionContentProtectionSessionIdentifierChangedNotification, NSString *)
-
-@interface AVStreamDataParser : NSObject
-- (void)processContentKeyResponseData:(NSData *)contentKeyResponseData forTrackID:(CMPersistentTrackID)trackID;
-- (void)processContentKeyResponseError:(NSError *)error forTrackID:(CMPersistentTrackID)trackID;
-- (void)renewExpiringContentKeyResponseDataForTrackID:(CMPersistentTrackID)trackID;
-- (NSData *)streamingContentKeyRequestDataForApp:(NSData *)appIdentifier contentIdentifier:(NSData *)contentIdentifier trackID:(CMPersistentTrackID)trackID options:(NSDictionary *)options error:(NSError **)outError;
-@end
-
-@interface AVStreamSession : NSObject
-- (void)addStreamDataParser:(AVStreamDataParser *)streamDataParser;
-- (void)removeStreamDataParser:(AVStreamDataParser *)streamDataParser;
-- (void)expire;
-- (NSData *)contentProtectionSessionIdentifier;
-+ (NSArray *)pendingExpiredSessionReportsWithAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
-+ (void)removePendingExpiredSessionReports:(NSArray *)expiredSessionReports withAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL;
-@end
-
-@interface CDMSessionMediaSourceAVFObjCObserver : NSObject {
-    WebCore::CDMSessionMediaSourceAVFObjC *m_parent;
-}
-@end
-
-@implementation CDMSessionMediaSourceAVFObjCObserver
-- (id)initWithParent:(WebCore::CDMSessionMediaSourceAVFObjC *)parent
-{
-    if ((self = [super init]))
-        m_parent = parent;
-    return self;
-}
-
-- (void)contentProtectionSessionIdentifierChanged:(NSNotification *)notification
-{
-    AVStreamSession* streamSession = (AVStreamSession*)[notification object];
-
-    NSData* identifier = [streamSession contentProtectionSessionIdentifier];
-    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:NSUTF8StringEncoding]) : nil;
-
-    if (m_parent)
-        m_parent-&gt;setSessionId(sessionIdentifierString.get());
-}
-@end
-
-static const NSString *PlaybackSessionIdKey = @&quot;PlaybackSessionID&quot;;
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC(const Vector&lt;int&gt;&amp; protocolVersions)
-    : m_client(nullptr)
-    , m_dataParserObserver(adoptNS([[CDMSessionMediaSourceAVFObjCObserver alloc] initWithParent:this]))
-    , m_protocolVersions(protocolVersions)
-    , m_mode(Normal)
</del><ins>+CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC(CDMPrivateMediaSourceAVFObjC&amp; cdm, CDMSessionClient* client)
+    : m_cdm(&amp;cdm)
+    , m_client(client)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CDMSessionMediaSourceAVFObjC::~CDMSessionMediaSourceAVFObjC()
</span><span class="cx"> {
</span><del>-    for (auto&amp; sourceBuffer : m_sourceBuffers) {
-        if (m_streamSession)
-            [m_streamSession removeStreamDataParser:sourceBuffer-&gt;parser()];
-    }
-
-    setStreamSession(nullptr);
</del><ins>+    if (m_cdm)
+        m_cdm-&gt;invalidateSession(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;Uint8Array&gt; CDMSessionMediaSourceAVFObjC::generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
-{
-    UNUSED_PARAM(mimeType);
-    UNUSED_PARAM(destinationURL);
-    ASSERT(initData);
-
-    LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::generateKeyRequest(%p)&quot;, this);
-
-    errorCode = MediaPlayer::NoError;
-    systemCode = 0;
-
-    m_initData = initData;
-
-    if (equalIgnoringCase(mimeType, &quot;keyrelease&quot;)) {
-        m_mode = KeyRelease;
-        return generateKeyReleaseMessage(errorCode, systemCode);
-    }
-
-    String certificateString(ASCIILiteral(&quot;certificate&quot;));
-    RefPtr&lt;Uint8Array&gt; array = Uint8Array::create(certificateString.length());
-    for (unsigned i = 0, length = certificateString.length(); i &lt; length; ++i)
-        array-&gt;set(i, certificateString[i]);
-    return array;
-}
-
-void CDMSessionMediaSourceAVFObjC::releaseKeys()
-{
-    if (m_streamSession) {
-        m_stopped = true;
-        for (auto&amp; sourceBuffer : m_sourceBuffers)
-            sourceBuffer-&gt;flush();
-
-        LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::releaseKeys(%p) - expiring stream session&quot;, this);
-        [m_streamSession expire];
-
-        if (!m_certificate)
-            return;
-
-        if (![getAVStreamSessionClass() respondsToSelector:@selector(pendingExpiredSessionReportsWithAppIdentifier:storageDirectoryAtURL:)])
-            return;
-
-        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
-        NSArray* expiredSessions = [getAVStreamSessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
-        for (NSData* expiredSessionData in expiredSessions) {
-            NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr];
-            NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey];
-            if (![playbackSessionIdValue isKindOfClass:[NSString class]])
-                continue;
-
-            if (m_sessionId == String(playbackSessionIdValue)) {
-                LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::releaseKeys(%p) - found session, sending expiration message&quot;);
-                m_expiredSession = expiredSessionData;
-                m_client-&gt;sendMessage(Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]).get(), emptyString());
-                break;
-            }
-        }
-    }
-}
-
-static bool isEqual(Uint8Array* data, const char* literal)
-{
-    ASSERT(data);
-    ASSERT(literal);
-    unsigned length = data-&gt;length();
-
-    for (unsigned i = 0; i &lt; length; ++i) {
-        if (!literal[i])
-            return false;
-
-        if (data-&gt;item(i) != static_cast&lt;uint8_t&gt;(literal[i]))
-            return false;
-    }
-    return !literal[length];
-}
-
-static NSInteger systemCodeForError(NSError *error)
-{
-    NSInteger code = [error code];
-    if (code != AVErrorUnknown)
-        return code;
-
-    NSError* underlyingError = [error.userInfo valueForKey:NSUnderlyingErrorKey];
-    if (!underlyingError || ![underlyingError isKindOfClass:[NSError class]])
-        return code;
-    
-    return [underlyingError code];
-}
-
-bool CDMSessionMediaSourceAVFObjC::update(Uint8Array* key, RefPtr&lt;Uint8Array&gt;&amp; nextMessage, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
-{
-    bool shouldGenerateKeyRequest = !m_certificate || isEqual(key, &quot;renew&quot;);
-    if (!m_certificate) {
-        LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::update(%p) - certificate data&quot;, this);
-
-        m_certificate = key;
-    }
-
-    if (isEqual(key, &quot;acknowledged&quot;)) {
-        LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::update(%p) - acknowleding secure stop message&quot;, this);
-
-        if (!m_expiredSession) {
-            errorCode = MediaPlayer::InvalidPlayerState;
-            return false;
-        }
-
-        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
-
-        if ([getAVStreamSessionClass() respondsToSelector:@selector(removePendingExpiredSessionReports:withAppIdentifier:storageDirectoryAtURL:)])
-            [getAVStreamSessionClass() removePendingExpiredSessionReports:@[m_expiredSession.get()] withAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
-        m_expiredSession = nullptr;
-        return true;
-    }
-
-    if (m_mode == KeyRelease)
-        return false;
-
-    RefPtr&lt;SourceBufferPrivateAVFObjC&gt; protectedSourceBuffer;
-    for (auto&amp; sourceBuffer : m_sourceBuffers) {
-        if (sourceBuffer-&gt;protectedTrackID() != -1) {
-            protectedSourceBuffer = sourceBuffer;
-            break;
-        }
-    }
-
-    if (shouldGenerateKeyRequest) {
-        RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
-
-        if (m_sourceBuffers.isEmpty())
-            return true;
-
-        if (!protectedSourceBuffer)
-            return true;
-
-        RetainPtr&lt;NSData&gt; initData = adoptNS([[NSData alloc] initWithBytes:m_initData-&gt;data() length:m_initData-&gt;length()]);
-
-
-        RetainPtr&lt;NSDictionary&gt; options;
-        if (!m_protocolVersions.isEmpty() &amp;&amp; canLoadAVStreamDataParserContentKeyRequestProtocolVersionsKey()) {
-            RetainPtr&lt;NSMutableArray&gt; protocolVersionsOption = adoptNS([[NSMutableArray alloc] init]);
-            for (auto&amp; version : m_protocolVersions) {
-                if (!version)
-                    continue;
-                [protocolVersionsOption addObject:@(version)];
-            }
-
-            options = @{ getAVStreamDataParserContentKeyRequestProtocolVersionsKey(): protocolVersionsOption.get() };
-        }
-
-        NSError* error = nil;
-        RetainPtr&lt;NSData&gt; request = [protectedSourceBuffer-&gt;parser() streamingContentKeyRequestDataForApp:certificateData.get() contentIdentifier:initData.get() trackID:protectedSourceBuffer-&gt;protectedTrackID() options:options.get() error:&amp;error];
-
-        if (![protectedSourceBuffer-&gt;parser() respondsToSelector:@selector(contentProtectionSessionIdentifier)])
-            m_sessionId = createCanonicalUUIDString();
-
-        if (error) {
-            LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::update(%p) - error:%@&quot;, this, [error description]);
-            errorCode = MediaPlayer::InvalidPlayerState;
-            systemCode = std::abs(systemCodeForError(error));
-            return false;
-        }
-
-        nextMessage = Uint8Array::create([request length]);
-        [request getBytes:nextMessage-&gt;data() length:nextMessage-&gt;length()];
-        return false;
-    }
-
-    ASSERT(!m_sourceBuffers.isEmpty());
-    LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::update(%p) - key data&quot;, this);
-    errorCode = MediaPlayer::NoError;
-    systemCode = 0;
-    RetainPtr&lt;NSData&gt; keyData = adoptNS([[NSData alloc] initWithBytes:key-&gt;data() length:key-&gt;length()]);
-    [protectedSourceBuffer-&gt;parser() processContentKeyResponseData:keyData.get() forTrackID:protectedSourceBuffer-&gt;protectedTrackID()];
-
-    return true;
-}
-
</del><span class="cx"> void CDMSessionMediaSourceAVFObjC::layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *error, bool&amp; shouldIgnore)
</span><span class="cx"> {
</span><span class="cx">     if (!m_client)
</span><span class="lines">@@ -315,29 +73,14 @@
</span><span class="cx">         m_client-&gt;sendError(CDMSessionClient::MediaKeyErrorDomain, code);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CDMSessionMediaSourceAVFObjC::setStreamSession(AVStreamSession *streamSession)
-{
-    if (m_streamSession &amp;&amp; canLoadAVStreamSessionContentProtectionSessionIdentifierChangedNotification())
-        [[NSNotificationCenter defaultCenter] removeObserver:m_dataParserObserver.get() name:getAVStreamSessionContentProtectionSessionIdentifierChangedNotification() object:m_streamSession.get()];
</del><span class="cx"> 
</span><del>-    m_streamSession = streamSession;
-
-    if (!m_streamSession)
-        return;
-
-    if (canLoadAVStreamSessionContentProtectionSessionIdentifierChangedNotification())
-        [[NSNotificationCenter defaultCenter] addObserver:m_dataParserObserver.get() selector:@selector(contentProtectionSessionIdentifierChanged:) name:getAVStreamSessionContentProtectionSessionIdentifierChangedNotification() object:m_streamSession.get()];
-
-    NSData* identifier = [streamSession contentProtectionSessionIdentifier];
-    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:(NSUTF8StringEncoding)]) : nil;
-    setSessionId(sessionIdentifierString.get());
-}
-
</del><span class="cx"> void CDMSessionMediaSourceAVFObjC::addSourceBuffer(SourceBufferPrivateAVFObjC* sourceBuffer)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_sourceBuffers.contains(sourceBuffer));
</span><span class="cx">     ASSERT(sourceBuffer);
</span><span class="cx"> 
</span><ins>+    addParser(sourceBuffer-&gt;parser());
+
</ins><span class="cx">     m_sourceBuffers.append(sourceBuffer);
</span><span class="cx">     sourceBuffer-&gt;registerForErrorNotifications(this);
</span><span class="cx"> }
</span><span class="lines">@@ -347,47 +90,30 @@
</span><span class="cx">     ASSERT(m_sourceBuffers.contains(sourceBuffer));
</span><span class="cx">     ASSERT(sourceBuffer);
</span><span class="cx"> 
</span><del>-    if (m_streamSession)
-        [m_streamSession removeStreamDataParser:sourceBuffer-&gt;parser()];
</del><ins>+    removeParser(sourceBuffer-&gt;parser());
</ins><span class="cx"> 
</span><span class="cx">     sourceBuffer-&gt;unregisterForErrorNotifications(this);
</span><span class="cx">     m_sourceBuffers.remove(m_sourceBuffers.find(sourceBuffer));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String CDMSessionMediaSourceAVFObjC::storagePath() const
</del><ins>+long CDMSessionMediaSourceAVFObjC::systemCodeForError(NSError *error)
</ins><span class="cx"> {
</span><del>-    return m_client ? pathByAppendingComponent(m_client-&gt;mediaKeysStorageDirectory(), &quot;SecureStop.plist&quot;) : emptyString();
-}
</del><ins>+    NSInteger code = [error code];
+    if (code != AVErrorUnknown)
+        return code;
</ins><span class="cx"> 
</span><del>-PassRefPtr&lt;Uint8Array&gt; CDMSessionMediaSourceAVFObjC::generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode)
-{
-    ASSERT(m_mode == KeyRelease);
-    m_certificate = m_initData;
-    RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
</del><ins>+    NSError* underlyingError = [error.userInfo valueForKey:NSUnderlyingErrorKey];
+    if (!underlyingError || ![underlyingError isKindOfClass:[NSError class]])
+        return code;
</ins><span class="cx"> 
</span><del>-    if (![getAVStreamSessionClass() respondsToSelector:@selector(pendingExpiredSessionReportsWithAppIdentifier:storageDirectoryAtURL:)]) {
-        errorCode = MediaPlayer::KeySystemNotSupported;
-        systemCode = '!mor';
-        return nullptr;
-    }
</del><ins>+    return [underlyingError code];
+}
</ins><span class="cx"> 
</span><del>-    NSArray* expiredSessions = [getAVStreamSessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:storagePath()]];
-    if (![expiredSessions count]) {
-        LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::generateKeyReleaseMessage(%p) - no expired sessions found&quot;, this);
-
-        errorCode = MediaPlayer::KeySystemNotSupported;
-        systemCode = '!mor';
-        return nullptr;
-    }
-
-    LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::generateKeyReleaseMessage(%p) - found %d expired sessions&quot;, this, [expiredSessions count]);
-
-    errorCode = 0;
-    systemCode = 0;
-    m_expiredSession = [expiredSessions firstObject];
-    return Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]);
</del><ins>+String CDMSessionMediaSourceAVFObjC::storagePath() const
+{
+    return m_client ? pathByAppendingComponent(m_client-&gt;mediaKeysStorageDirectory(), &quot;SecureStop.plist&quot;) : emptyString();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+#endif // ENABLE(ENCRYPTED_MEDIA_V2) &amp;&amp; ENABLE(MEDIA_SOURCE)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -255,7 +255,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><del>-    std::unique_ptr&lt;CDMSession&gt; createSession(const String&amp; keySystem) override;
</del><ins>+    std::unique_ptr&lt;CDMSession&gt; createSession(const String&amp; keySystem, CDMSessionClient*) override;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     virtual String languageOfPrimaryAudioTrack() const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -162,6 +162,7 @@
</span><span class="cx"> #import &quot;CoreMediaSoftLink.h&quot;
</span><span class="cx"> 
</span><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
</span><ins>+
</ins><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(CoreImage)
</span><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(CoreVideo)
</span><span class="cx"> 
</span><span class="lines">@@ -2766,12 +2767,12 @@
</span><span class="cx">         m_keyURIToRequestMap.remove(keyId);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;CDMSession&gt; MediaPlayerPrivateAVFoundationObjC::createSession(const String&amp; keySystem)
</del><ins>+std::unique_ptr&lt;CDMSession&gt; MediaPlayerPrivateAVFoundationObjC::createSession(const String&amp; keySystem, CDMSessionClient* client)
</ins><span class="cx"> {
</span><span class="cx">     if (!keySystemIsSupported(keySystem))
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    return std::make_unique&lt;CDMSessionAVFoundationObjC&gt;(this);
</del><ins>+    return std::make_unique&lt;CDMSessionAVFoundationObjC&gt;(this, client);
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx">     bool hasStreamSession() { return m_streamSession; }
</span><span class="cx">     AVStreamSession *streamSession();
</span><span class="cx">     virtual void setCDMSession(CDMSession*) override;
</span><ins>+    CDMSessionMediaSourceAVFObjC* cdmSession() const { return m_session; }
</ins><span class="cx">     void keyNeeded(Uint8Array*);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><ins>+#import &quot;CDMSessionAVStreamSession.h&quot;
</ins><span class="cx"> #import &quot;CDMSessionMediaSourceAVFObjC.h&quot;
</span><span class="cx"> #import &quot;FileSystem.h&quot;
</span><span class="cx"> #import &quot;Logging.h&quot;
</span><span class="lines">@@ -703,19 +704,15 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaSourceAVFObjC::setCDMSession(CDMSession* session)
</span><span class="cx"> {
</span><del>-    if (m_session) {
-        for (auto&amp; sourceBuffer : m_mediaSourcePrivate-&gt;sourceBuffers())
-            m_session-&gt;removeSourceBuffer(sourceBuffer.get());
-        m_session = nullptr;
-    }
</del><ins>+    if (session == m_session)
+        return;
</ins><span class="cx"> 
</span><span class="cx">     m_session = toCDMSessionMediaSourceAVFObjC(session);
</span><span class="cx"> 
</span><del>-    if (m_session) {
-        m_session-&gt;setStreamSession(m_streamSession.get());
-        for (auto&amp; sourceBuffer : m_mediaSourcePrivate-&gt;sourceBuffers())
-            m_session-&gt;addSourceBuffer(sourceBuffer.get());
-    }
</del><ins>+    if (CDMSessionAVStreamSession* cdmStreamSession = toCDMSessionAVStreamSession(m_session))
+        cdmStreamSession-&gt;setStreamSession(m_streamSession.get());
+    for (auto&amp; sourceBuffer : m_mediaSourcePrivate-&gt;sourceBuffers())
+        sourceBuffer-&gt;setCDMSession(m_session);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded(Uint8Array* initData)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -29,9 +29,11 @@
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;SourceBufferPrivate.h&quot;
</span><ins>+#include &lt;dispatch/semaphore.h&gt;
</ins><span class="cx"> #include &lt;wtf/Deque.h&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/MediaTime.h&gt;
</span><ins>+#include &lt;wtf/OSObjectPtr.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -53,6 +55,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class CDMSessionMediaSourceAVFObjC;
</ins><span class="cx"> class MediaSourcePrivateAVFObjC;
</span><span class="cx"> class TimeRanges;
</span><span class="cx"> class AudioTrackPrivate;
</span><span class="lines">@@ -80,7 +83,7 @@
</span><span class="cx">     void didProvideMediaDataForTrackID(int trackID, CMSampleBufferRef, const String&amp; mediaType, unsigned flags);
</span><span class="cx">     void didReachEndOfTrackWithTrackID(int trackID, const String&amp; mediaType);
</span><span class="cx">     void willProvideContentKeyRequestInitializationDataForTrackID(int trackID);
</span><del>-    void didProvideContentKeyRequestInitializationDataForTrackID(NSData*, int trackID);
</del><ins>+    void didProvideContentKeyRequestInitializationDataForTrackID(NSData*, int trackID, OSObjectPtr&lt;dispatch_semaphore_t&gt;);
</ins><span class="cx"> 
</span><span class="cx">     bool processCodedFrame(int trackID, CMSampleBufferRef, const String&amp; mediaType);
</span><span class="cx"> 
</span><span class="lines">@@ -96,6 +99,7 @@
</span><span class="cx"> 
</span><span class="cx">     int protectedTrackID() const { return m_protectedTrackID; }
</span><span class="cx">     AVStreamDataParser* parser() const { return m_parser.get(); }
</span><ins>+    void setCDMSession(CDMSessionMediaSourceAVFObjC*);
</ins><span class="cx"> 
</span><span class="cx">     void flush();
</span><span class="cx"> 
</span><span class="lines">@@ -142,9 +146,11 @@
</span><span class="cx">     HashMap&lt;int, RetainPtr&lt;AVSampleBufferAudioRenderer&gt;&gt; m_audioRenderers;
</span><span class="cx">     RetainPtr&lt;WebAVStreamDataParserListener&gt; m_delegate;
</span><span class="cx">     RetainPtr&lt;WebAVSampleBufferErrorListener&gt; m_errorListener;
</span><ins>+    OSObjectPtr&lt;dispatch_semaphore_t&gt; m_hasSessionSemaphore;
</ins><span class="cx"> 
</span><span class="cx">     MediaSourcePrivateAVFObjC* m_mediaSource;
</span><span class="cx">     SourceBufferPrivateClient* m_client;
</span><ins>+    CDMSessionMediaSourceAVFObjC* m_session { nullptr };
</ins><span class="cx"> 
</span><span class="cx">     FloatSize m_cachedSize;
</span><span class="cx">     bool m_parsingSucceeded;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -255,11 +255,6 @@
</span><span class="cx"> #endif
</span><span class="cx">     ASSERT(streamDataParser == _parser);
</span><span class="cx"> 
</span><del>-    if (isMainThread()) {
-        _parent-&gt;willProvideContentKeyRequestInitializationDataForTrackID(trackID);
-        return;
-    }
-
</del><span class="cx">     // We must call synchronously to the main thread, as the AVStreamSession must be associated
</span><span class="cx">     // with the streamDataParser before the delegate method returns.
</span><span class="cx">     RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</span><span class="lines">@@ -278,10 +273,12 @@
</span><span class="cx">     RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;NSData&gt; strongData = initData;
</span><del>-    callOnMainThread([strongSelf, strongData, trackID] {
</del><ins>+    OSObjectPtr&lt;dispatch_semaphore_t&gt; hasSessionSemaphore = adoptOSObject(dispatch_semaphore_create(0));
+    callOnMainThread([strongSelf, strongData, trackID,  hasSessionSemaphore] {
</ins><span class="cx">         if (strongSelf-&gt;_parent)
</span><del>-            strongSelf-&gt;_parent-&gt;didProvideContentKeyRequestInitializationDataForTrackID(strongData.get(), trackID);
</del><ins>+            strongSelf-&gt;_parent-&gt;didProvideContentKeyRequestInitializationDataForTrackID(strongData.get(), trackID, hasSessionSemaphore);
</ins><span class="cx">     });
</span><ins>+    dispatch_semaphore_wait(hasSessionSemaphore.get(), DISPATCH_TIME_FOREVER);
</ins><span class="cx"> }
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="lines">@@ -614,6 +611,9 @@
</span><span class="cx">     ASSERT(!m_client);
</span><span class="cx">     destroyParser();
</span><span class="cx">     destroyRenderers();
</span><ins>+
+    if (m_hasSessionSemaphore)
+        dispatch_semaphore_signal(m_hasSessionSemaphore.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset(AVAsset* asset)
</span><span class="lines">@@ -719,15 +719,14 @@
</span><span class="cx">     LOG(MediaSource, &quot;SourceBufferPrivateAVFObjC::willProvideContentKeyRequestInitializationDataForTrackID(%p) - track:%d&quot;, this, trackID);
</span><span class="cx">     m_protectedTrackID = trackID;
</span><span class="cx"> 
</span><del>-    BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    [m_mediaSource-&gt;player()-&gt;streamSession() addStreamDataParser:m_parser.get()];
-    END_BLOCK_OBJC_EXCEPTIONS;
</del><ins>+    if (CDMSessionMediaSourceAVFObjC* session = m_mediaSource-&gt;player()-&gt;cdmSession())
+        session-&gt;addParser(m_parser.get());
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(trackID);
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(NSData* initData, int trackID)
</del><ins>+void SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(NSData* initData, int trackID, OSObjectPtr&lt;dispatch_semaphore_t&gt; hasSessionSemaphore)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_mediaSource)
</span><span class="cx">         return;
</span><span class="lines">@@ -739,6 +738,14 @@
</span><span class="cx">     RefPtr&lt;Uint8Array&gt; initDataArray = Uint8Array::create([initData length]);
</span><span class="cx">     [initData getBytes:initDataArray-&gt;data() length:initDataArray-&gt;length()];
</span><span class="cx">     m_mediaSource-&gt;sourceBufferKeyNeeded(this, initDataArray.get());
</span><ins>+    if (auto session = m_mediaSource-&gt;player()-&gt;cdmSession()) {
+        session-&gt;addParser(m_parser.get());
+        dispatch_semaphore_signal(hasSessionSemaphore.get());
+    } else {
+        if (m_hasSessionSemaphore)
+            dispatch_semaphore_signal(m_hasSessionSemaphore.get());
+        m_hasSessionSemaphore = hasSessionSemaphore;
+    }
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(initData);
</span><span class="cx"> #endif
</span><span class="lines">@@ -921,6 +928,25 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBufferPrivateAVFObjC::setCDMSession(CDMSessionMediaSourceAVFObjC* session)
+{
+    if (session == m_session)
+        return;
+
+    if (m_session)
+        m_session-&gt;removeSourceBuffer(this);
+
+    m_session = session;
+
+    if (m_session) {
+        m_session-&gt;addSourceBuffer(this);
+        if (m_hasSessionSemaphore) {
+            dispatch_semaphore_signal(m_hasSessionSemaphore.get());
+            m_hasSessionSemaphore = nullptr;
+        }
+    }
+}
+
</ins><span class="cx"> void SourceBufferPrivateAVFObjC::flush()
</span><span class="cx"> {
</span><span class="cx">     if (m_displayLayer)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscacocoaPlatformCALayerCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -66,6 +66,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
</span><ins>+
</ins><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer)
</span><span class="cx"> 
</span><span class="cx"> using namespace WebCore;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockCDM.cpp (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDM.cpp        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/testing/MockCDM.cpp        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> class MockCDMSession : public CDMSession {
</span><span class="cx"> public:
</span><del>-    MockCDMSession();
</del><ins>+    MockCDMSession(CDMSessionClient*);
</ins><span class="cx">     virtual ~MockCDMSession() { }
</span><span class="cx"> 
</span><span class="cx">     virtual void setClient(CDMSessionClient* client) override { m_client = client; }
</span><span class="lines">@@ -71,9 +71,9 @@
</span><span class="cx">     return equalIgnoringCase(mimeType, &quot;video/mock&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;CDMSession&gt; MockCDM::createSession()
</del><ins>+std::unique_ptr&lt;CDMSession&gt; MockCDM::createSession(CDMSessionClient* client)
</ins><span class="cx"> {
</span><del>-    return std::make_unique&lt;MockCDMSession&gt;();
</del><ins>+    return std::make_unique&lt;MockCDMSession&gt;(client);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static Uint8Array* initDataPrefix()
</span><span class="lines">@@ -106,8 +106,9 @@
</span><span class="cx">     return String::number(monotonicallyIncreasingSessionId++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MockCDMSession::MockCDMSession()
-    : m_sessionId(generateSessionId())
</del><ins>+MockCDMSession::MockCDMSession(CDMSessionClient* client)
+    : m_client(client)
+    , m_sessionId(generateSessionId())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockCDM.h (193478 => 193479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDM.h        2015-12-04 22:38:27 UTC (rev 193478)
+++ trunk/Source/WebCore/testing/MockCDM.h        2015-12-04 22:41:44 UTC (rev 193479)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">     virtual ~MockCDM() { }
</span><span class="cx"> 
</span><span class="cx">     virtual bool supportsMIMEType(const String&amp; mimeType) override;
</span><del>-    virtual std::unique_ptr&lt;CDMSession&gt; createSession() override;
</del><ins>+    virtual std::unique_ptr&lt;CDMSession&gt; createSession(CDMSessionClient*) override;
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     CDM* m_cdm;
</span></span></pre>
</div>
</div>

</body>
</html>