bb78fdc07c65bcc7601dd1f321721adbd1ea7024
[WebKit-https.git] / Source / WebCore / Modules / encryptedmedia / CDMPrivateAVFoundation.mm
1 /*
2  * Copyright (C) 2012 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 #import "config.h"
27 #import "CDMPrivateAVFoundation.h"
28
29 #if ENABLE(ENCRYPTED_MEDIA_V2) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
30
31 #import "CDM.h"
32 #import "ExceptionCode.h"
33 #import "MediaPlayer.h"
34 #import "MediaPlayerPrivateAVFoundationObjC.h"
35 #import "SoftLinking.h"
36 #import "UUID.h"
37 #import <AVFoundation/AVFoundation.h>
38 #import <objc/objc-runtime.h>
39
40 namespace WebCore {
41
42 class CDMSessionAVFoundation : public CDMSession {
43 public:
44     CDMSessionAVFoundation(CDMPrivateAVFoundation* parent);
45     virtual ~CDMSessionAVFoundation() { }
46
47     virtual const String& sessionId() const OVERRIDE { return m_sessionId; }
48     virtual PassRefPtr<Uint8Array> generateKeyRequest(const String& mimeType, Uint8Array* initData, String& destinationURL, unsigned short& errorCode, unsigned long& systemCode) OVERRIDE;
49     virtual void releaseKeys() OVERRIDE;
50     virtual bool update(Uint8Array*, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, unsigned long& systemCode) OVERRIDE;
51
52 protected:
53     CDMPrivateAVFoundation* m_parent;
54     String m_sessionId;
55     RetainPtr<AVAssetResourceLoadingRequest> m_request;
56 };
57
58 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
59 SOFT_LINK_CLASS(AVFoundation, AVURLAsset)
60 SOFT_LINK_CLASS(AVFoundation, AVAssetResourceLoadingRequest)
61 #define AVURLAsset getAVURLAssetClass()
62 #define AVAssetResourceLoadingRequest getAVAssetResourceLoadingRequest()
63
64
65 bool CDMPrivateAVFoundation::supportsKeySystem(const String& keySystem)
66 {
67     return equalIgnoringCase(keySystem, "com.apple.fps") || equalIgnoringCase(keySystem, "com.apple.fps.1_0");
68 }
69
70 bool CDMPrivateAVFoundation::supportsKeySystemAndMimeType(const String& keySystem, const String& mimeType)
71 {
72     if (!supportsKeySystem(keySystem))
73         return false;
74     return [AVURLAsset isPlayableExtendedMIMEType:mimeType];
75 }
76
77 bool CDMPrivateAVFoundation::supportsMIMEType(const String& mimeType)
78 {
79     return [AVURLAsset isPlayableExtendedMIMEType:mimeType];
80 }
81
82 PassOwnPtr<CDMSession> CDMPrivateAVFoundation::createSession()
83 {
84     return adoptPtr(new CDMSessionAVFoundation(this));
85 }
86
87 CDMSessionAVFoundation::CDMSessionAVFoundation(CDMPrivateAVFoundation* parent)
88     : m_parent(parent)
89     , m_sessionId(createCanonicalUUIDString())
90 {
91 }
92
93 PassRefPtr<Uint8Array> CDMSessionAVFoundation::generateKeyRequest(const String& mimeType, Uint8Array* initData, String& destinationURL, unsigned short& errorCode, unsigned long& systemCode)
94 {
95     UNUSED_PARAM(mimeType);
96
97     MediaPlayer* mediaPlayer = m_parent->cdm()->mediaPlayer();
98     if (!mediaPlayer) {
99         errorCode = NOT_SUPPORTED_ERR;
100         return 0;
101     }
102
103     String keyURI;
104     String keyID;
105     RefPtr<Uint8Array> certificate;
106     if (!MediaPlayerPrivateAVFoundationObjC::extractKeyURIKeyIDAndCertificateFromInitData(initData, keyURI, keyID, certificate)) {
107         errorCode = INVALID_STATE_ERR;
108         return 0;
109     }
110
111     m_request = MediaPlayerPrivateAVFoundationObjC::takeRequestForPlayerAndKeyURI(mediaPlayer, keyURI);
112     if (!m_request) {
113         errorCode = INVALID_STATE_ERR;
114         return 0;
115     }
116
117     m_sessionId = createCanonicalUUIDString();
118
119     RetainPtr<NSData> certificateData = adoptNS([[NSData alloc] initWithBytes:certificate->baseAddress() length:certificate->byteLength()]);
120     NSString* assetStr = keyID;
121     RetainPtr<NSData> assetID = [NSData dataWithBytes: [assetStr cStringUsingEncoding:NSUTF8StringEncoding] length:[assetStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
122     NSError* error = 0;
123     RetainPtr<NSData> keyRequest = [m_request.get() streamingContentKeyRequestDataForApp:certificateData.get() contentIdentifier:assetID.get() options:nil error:&error];
124
125     if (!keyRequest) {
126         NSError* underlyingError = [[error userInfo] objectForKey:NSUnderlyingErrorKey];
127         errorCode = CDM::DomainError;
128         systemCode = [underlyingError code];
129         return 0;
130     }
131
132     errorCode = 0;
133     systemCode = 0;
134     destinationURL = String();
135
136     RefPtr<ArrayBuffer> keyRequestBuffer = ArrayBuffer::create([keyRequest.get() bytes], [keyRequest.get() length]);
137     return Uint8Array::create(keyRequestBuffer, 0, keyRequestBuffer->byteLength());
138 }
139
140 void CDMSessionAVFoundation::releaseKeys()
141 {
142 }
143
144 bool CDMSessionAVFoundation::update(Uint8Array* key, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, unsigned long& systemCode)
145 {
146     if (!key)
147         return false;
148
149     RetainPtr<NSData> keyData = adoptNS([[NSData alloc] initWithBytes:key->baseAddress() length:key->byteLength()]);
150     [[m_request.get() dataRequest] respondWithData:keyData.get()];
151     [m_request.get() finishLoading];
152     errorCode = 0;
153     systemCode = 0;
154     nextMessage = nullptr;
155
156     return true;
157 }
158
159 }
160
161 #endif