[EME] Implement MediaKeys.isTypeSupported()
[WebKit-https.git] / Source / WebCore / Modules / encryptedmedia / MediaKeys.cpp
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MediaKeys.h"
28
29 #if ENABLE(ENCRYPTED_MEDIA_V2)
30
31 #include "CDM.h"
32 #include "EventNames.h"
33 #include "HTMLMediaElement.h"
34 #include "MediaKeyMessageEvent.h"
35 #include "MediaKeySession.h"
36 #include "UUID.h"
37 #include <wtf/HashSet.h>
38
39 namespace WebCore {
40
41 PassRefPtr<MediaKeys> MediaKeys::create(const String& keySystem, ExceptionCode& ec)
42 {
43     // From <http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-media-keys-constructor>:
44     // The MediaKeys(keySystem) constructor must run the following steps:
45
46     // 1. If keySystem is null or an empty string, throw an INVALID_ACCESS_ERR exception and abort these steps.
47     if (keySystem.isNull() || keySystem.isEmpty()) {
48         ec = INVALID_ACCESS_ERR;
49         return 0;
50     }
51
52     // 2. If keySystem is not one of the user agent's supported Key Systems, throw a NOT_SUPPORTED_ERR and abort these steps.
53     if (!CDM::supportsKeySystem(keySystem)) {
54         ec = NOT_SUPPORTED_ERR;
55         return 0;
56     }
57
58     // 3. Let cdm be the content decryption module corresponding to keySystem.
59     // 4. Load cdm if necessary.
60     OwnPtr<CDM> cdm = CDM::create(keySystem);
61
62     // 5. Create a new MediaKeys object.
63     // 5.1 Let the keySystem attribute be keySystem.
64     // 6. Return the new object to the caller.
65     return adoptRef(new MediaKeys(keySystem, cdm.release()));
66 }
67
68 MediaKeys::MediaKeys(const String& keySystem, PassOwnPtr<CDM> cdm)
69     : m_mediaElement(0)
70     , m_keySystem(keySystem)
71     , m_cdm(cdm)
72 {
73     m_cdm->setClient(this);
74 }
75
76 MediaKeys::~MediaKeys()
77 {
78     // From <http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-media-keys-constructor>:
79     // When destroying a MediaKeys object, follow the steps in close().
80     for (size_t i = 0; i < m_sessions.size(); ++i) {
81         m_sessions[i]->close();
82         m_sessions[i]->setKeys(0);
83     }
84 }
85
86 PassRefPtr<MediaKeySession> MediaKeys::createSession(ScriptExecutionContext* context, const String& type, Uint8Array* initData, ExceptionCode& ec)
87 {
88     // From <http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-createsession>:
89     // The createSession(type, initData) method must run the following steps:
90     // Note: The contents of initData are container-specific Initialization Data.
91
92     // 1. If type is null or an empty string and initData is not null or an empty string, throw an
93     // INVALID_ACCESS_ERR exception and abort these steps.
94     if ((type.isNull() || type.isEmpty()) && (!initData || initData->length())) {
95         ec = INVALID_ACCESS_ERR;
96         return 0;
97     }
98
99     // 2. If type contains a MIME type that is not supported or is not supported by the keySystem, throw
100     // a NOT_SUPPORTED_ERR exception and abort these steps.
101     if (!type.isNull() && !type.isEmpty() && !m_cdm->supportsMIMEType(type)) {
102         ec = NOT_SUPPORTED_ERR;
103         return 0;
104     }
105
106     // 3. Create a new MediaKeySession object.
107     // 3.1 Let the keySystem attribute be keySystem.
108     // 3.2 Let the sessionId attribute be a unique Session ID string. It may be generated by cdm.
109     RefPtr<MediaKeySession> session = MediaKeySession::create(context, this, keySystem());
110
111     // 4. Add the new object to an internal list of session objects.
112     m_sessions.append(session);
113
114     // 5. Schedule a task to generate a key request, providing type, initData, and the new object.
115     session->generateKeyRequest(type, initData);
116
117     // 6. Return the new object to the caller.
118     return session;
119 }
120
121 bool MediaKeys::isTypeSupported(const String& keySystem, const String& mimeType)
122 {
123     // 1. If keySystem contains an unrecognized or unsupported Key System, return false and abort these steps.
124     // Key system string comparison is case-sensitive.
125     if (keySystem.isNull() || keySystem.isEmpty() || !CDM::supportsKeySystem(keySystem))
126         return false;
127
128     // 2. If type is null or an empty string, return true and abort these steps.
129     if (mimeType.isNull() || mimeType.isEmpty())
130         return true;
131
132     // 3. If the Key System specified by keySystem does not support decrypting the container and/or codec
133     // specified by type, return false and abort these steps.
134     if (!CDM::keySystemSupportsMimeType(keySystem, mimeType))
135         return false;
136
137     // 4. Return true;
138     return true;
139 }
140
141 void MediaKeys::setMediaElement(HTMLMediaElement* element)
142 {
143     m_mediaElement = element;
144 }
145
146 MediaPlayer* MediaKeys::cdmMediaPlayer(const CDM*) const
147 {
148     if (m_mediaElement)
149         return m_mediaElement->player();
150     return 0;
151 }
152
153 }
154
155 #endif