1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var keySystem
= QueryString
.keysystem
;
6 var mediaFile
= QueryString
.mediafile
;
7 var mediaType
= QueryString
.mediatype
|| 'video/webm; codecs="vorbis, vp8"';
8 var useMSE
= QueryString
.usemse
== 1;
10 // Default key used to encrypt many media files used in browser tests.
11 var KEY
= new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
12 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]);
13 // KEY_ID constant used as init data while encrypting test media files.
14 var KEY_ID
= getInitDataFromKeyId("0123456789012345");
15 // Heart beat message header.
16 var HEART_BEAT_HEADER
= 'HEARTBEAT';
17 var FILE_IO_TEST_RESULT_HEADER
= 'FILEIOTESTRESULT';
18 var EXTERNAL_CLEAR_KEY_KEY_SYSTEM
= "org.chromium.externalclearkey";
19 var EXTERNAL_CLEAR_KEY_FILE_IO_TEST_KEY_SYSTEM
=
20 "org.chromium.externalclearkey.fileiotest";
21 // Note that his URL has been normalized from the one in clear_key_cdm.cc.
22 var EXTERNAL_CLEAR_KEY_HEARTBEAT_URL
=
23 'http://test.externalclearkey.chromium.org/';
25 function hasPrefix(msg
, prefix
) {
26 if (msg
.length
< prefix
.length
)
28 for (var i
= 0; i
< prefix
.length
; ++i
) {
29 if (String
.fromCharCode(msg
[i
]) != prefix
[i
])
35 function isHeartbeatMessage(msg
) {
36 return hasPrefix(msg
, HEART_BEAT_HEADER
);
39 function isFileIOTestMessage(msg
) {
40 return hasPrefix(msg
, FILE_IO_TEST_RESULT_HEADER
);
43 function loadEncryptedMediaFromURL(video
) {
44 return loadEncryptedMedia(video
, mediaFile
, keySystem
, KEY
, useMSE
);
47 function loadEncryptedMedia(video
, mediaFile
, keySystem
, key
, useMSE
,
48 appendSourceCallbackFn
) {
49 var keyRequested
= false;
50 var sourceOpened
= false;
51 // Add properties to enable verification that events occurred.
52 video
.receivedKeyAdded
= false;
53 video
.receivedHeartbeat
= false;
54 video
.isHeartbeatExpected
= keySystem
=== EXTERNAL_CLEAR_KEY_KEY_SYSTEM
;
55 video
.receivedKeyMessage
= false;
57 if (!(video
&& mediaFile
&& keySystem
&& key
)) {
58 failTest('Missing parameters in loadEncryptedMedia().');
62 function onNeedKey(e
) {
66 console
.log('onNeedKey', e
);
68 video
.webkitGenerateKeyRequest(keySystem
, e
.initData
);
71 setResultInTitle(error
.name
);
75 function onKeyAdded(e
) {
76 e
.target
.receivedKeyAdded
= true;
79 function onKeyMessage(e
) {
80 video
.receivedKeyMessage
= true;
82 failTest('keymessage without a keySystem: ' + e
.keySystem
);
87 failTest('keymessage without a sessionId: ' + e
.sessionId
);
92 failTest('keymessage without a message: ' + e
.message
);
96 if (isHeartbeatMessage(e
.message
)) {
97 console
.log('onKeyMessage - heartbeat', e
);
98 e
.target
.receivedHeartbeat
= true;
99 verifyHeartbeatMessage(e
);
103 if (isFileIOTestMessage(e
.message
)) {
104 var success
= getFileIOTestResult(e
);
105 console
.log('onKeyMessage - CDM file IO test: ' +
106 (success
? 'Success' : 'Fail'));
108 setResultInTitle("FILEIOTESTSUCCESS");
110 setResultInTitle("FAILED");
114 // For FileIOTest key system, no need to start playback.
115 if (e
.keySystem
== EXTERNAL_CLEAR_KEY_FILE_IO_TEST_KEY_SYSTEM
)
118 // No tested key system returns defaultURL in for key request messages.
120 failTest('keymessage unexpectedly has defaultURL: ' + e
.defaultURL
);
124 // keymessage in response to generateKeyRequest. Reply with key.
125 console
.log('onKeyMessage - key request', e
);
126 var initData
= e
.message
;
127 if (mediaType
.indexOf('mp4') != -1)
128 initData
= KEY_ID
; // Temporary hack for Clear Key in v0.1.
129 video
.webkitAddKey(keySystem
, key
, initData
);
132 function verifyHeartbeatMessage(e
) {
133 String
.prototype.startsWith = function(prefix
) {
134 return this.indexOf(prefix
) === 0;
137 function isExternalClearKey(keySystem
) {
138 return keySystem
== EXTERNAL_CLEAR_KEY_KEY_SYSTEM
||
139 keySystem
.startsWith(EXTERNAL_CLEAR_KEY_KEY_SYSTEM
+ '.');
142 // Only External Clear Key sends a HEARTBEAT message.
143 if (!isExternalClearKey(e
.keySystem
)) {
144 failTest('Unexpected heartbeat from ' + e
.keySystem
);
148 if (e
.defaultURL
!= EXTERNAL_CLEAR_KEY_HEARTBEAT_URL
) {
149 failTest('Heartbeat message with unexpected defaultURL: ' + e
.defaultURL
);
154 function getFileIOTestResult(e
) {
155 // Only External Clear Key sends a FILEIOTESTRESULT message.
156 if (e
.keySystem
!= EXTERNAL_CLEAR_KEY_FILE_IO_TEST_KEY_SYSTEM
) {
157 failTest('Unexpected CDM file IO test result from ' + e
.keySystem
);
161 // The test result is either '0' or '1' appended to the header.
162 if (e
.message
.length
!= FILE_IO_TEST_RESULT_HEADER
.length
+ 1)
165 var result_index
= FILE_IO_TEST_RESULT_HEADER
.length
;
166 return String
.fromCharCode(e
.message
[result_index
]) == 1;
169 video
.addEventListener('webkitneedkey', onNeedKey
);
170 video
.addEventListener('webkitkeymessage', onKeyMessage
);
171 video
.addEventListener('webkitkeyerror', function() {
172 setResultInTitle("KeyError");
174 video
.addEventListener('webkitkeyadded', onKeyAdded
);
175 installTitleEventHandler(video
, 'error');
178 var mediaSource
= loadMediaSource(mediaFile
, mediaType
,
179 appendSourceCallbackFn
);
180 video
.src
= window
.URL
.createObjectURL(mediaSource
);
182 video
.src
= mediaFile
;
186 function getInitDataFromKeyId(keyID
) {
187 var init_key_id
= new Uint8Array(keyID
.length
);
188 for(var i
= 0; i
< keyID
.length
; i
++) {
189 init_key_id
[i
] = keyID
.charCodeAt(i
);