Add WTF::move()
[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     std::unique_ptr<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, WTF::move(cdm)));
66 }
67
68 MediaKeys::MediaKeys(const String& keySystem, std::unique_ptr<CDM> cdm)
69     : m_mediaElement(0)
70     , m_keySystem(keySystem)
71     , m_cdm(WTF::move(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 contentType is null or an empty string, throw an INVALID_ACCESS_ERR exception and abort these steps.
93     if (type.isEmpty()) {
94         ec = INVALID_ACCESS_ERR;
95         return 0;
96     }
97
98     // 2. If initData is null or an empty array, throw an INVALID_ACCESS_ERR exception and abort these steps.
99     if (!initData || !initData->length()) {
100         ec = INVALID_ACCESS_ERR;
101         return 0;
102     }
103
104     // 3. If type contains a MIME type that is not supported or is not supported by the keySystem, throw
105     // a NOT_SUPPORTED_ERR exception and abort these steps.
106     if (!type.isNull() && !type.isEmpty() && !m_cdm->supportsMIMEType(type)) {
107         ec = NOT_SUPPORTED_ERR;
108         return 0;
109     }
110
111     // 4. Create a new MediaKeySession object.
112     // 4.1 Let the keySystem attribute be keySystem.
113     // 4.2 Let the sessionId attribute be a unique Session ID string. It may be generated by cdm.
114     RefPtr<MediaKeySession> session = MediaKeySession::create(context, this, keySystem());
115
116     m_sessions.append(session);
117
118     // 5. Schedule a task to initialize the session, providing contentType, initData, and the new object.
119     session->generateKeyRequest(type, initData);
120
121     // 6. Return the new object to the caller.
122     return session;
123 }
124
125 bool MediaKeys::isTypeSupported(const String& keySystem, const String& mimeType)
126 {
127     // 1. If keySystem contains an unrecognized or unsupported Key System, return false and abort these steps.
128     // Key system string comparison is case-sensitive.
129     if (keySystem.isNull() || keySystem.isEmpty() || !CDM::supportsKeySystem(keySystem))
130         return false;
131
132     // 2. If type is null or an empty string, return true and abort these steps.
133     if (mimeType.isNull() || mimeType.isEmpty())
134         return true;
135
136     // 3. If the Key System specified by keySystem does not support decrypting the container and/or codec
137     // specified by type, return false and abort these steps.
138     if (!CDM::keySystemSupportsMimeType(keySystem, mimeType))
139         return false;
140
141     // 4. Return true;
142     return true;
143 }
144
145 void MediaKeys::setMediaElement(HTMLMediaElement* element)
146 {
147     m_mediaElement = element;
148 }
149
150 MediaPlayer* MediaKeys::cdmMediaPlayer(const CDM*) const
151 {
152     if (m_mediaElement)
153         return m_mediaElement->player();
154     return 0;
155 }
156
157 }
158
159 #endif