1 // Copyright (c) 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. 4 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; 9 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 EXTERNAL_CLEAR_KEY_KEY_SYSTEM = "org.chromium.externalclearkey"; 18 // Note that his URL has been normalized from the one in clear_key_cdm.cc. 19 var EXTERNAL_CLEAR_KEY_HEARTBEAT_URL = 20 'http://test.externalclearkey.chromium.org/'; 21 22 function isHeartbeatMessage(msg) { 23 if (msg.length < HEART_BEAT_HEADER.length) 24 return false; 25 for (var i = 0; i < HEART_BEAT_HEADER.length; ++i) { 26 if (String.fromCharCode(msg[i]) != HEART_BEAT_HEADER[i]) 27 return false; 28 } 29 return true; 30 } 31 32 function loadEncryptedMediaFromURL(video) { 33 return loadEncryptedMedia(video, mediaFile, keySystem, KEY, useMSE); 34 } 35 36 function loadEncryptedMedia(video, mediaFile, keySystem, key, useMSE, 37 appendSourceCallbackFn) { 38 var keyRequested = false; 39 var sourceOpened = false; 40 // Add properties to enable verification that events occurred. 41 video.receivedKeyAdded = false; 42 video.receivedHeartbeat = false; 43 video.isHeartbeatExpected = keySystem === EXTERNAL_CLEAR_KEY_KEY_SYSTEM; 44 video.receivedKeyMessage = false; 45 46 if (!(video && mediaFile && keySystem && key)) { 47 failTest('Missing parameters in loadEncryptedMedia().'); 48 return; 49 } 50 51 function onNeedKey(e) { 52 if (keyRequested) 53 return; 54 keyRequested = true; 55 console.log('onNeedKey', e); 56 try { 57 video.webkitGenerateKeyRequest(keySystem, e.initData); 58 } 59 catch(error) { 60 setResultInTitle(error.name); 61 } 62 } 63 64 function onKeyAdded(e) { 65 e.target.receivedKeyAdded = true; 66 } 67 68 function onKeyMessage(e) { 69 video.receivedKeyMessage = true; 70 if (!e.keySystem) { 71 failTest('keymessage without a keySystem: ' + e.keySystem); 72 return; 73 } 74 75 if (!e.sessionId) { 76 failTest('keymessage without a sessionId: ' + e.sessionId); 77 return; 78 } 79 80 if (!e.message) { 81 failTest('keymessage without a message: ' + e.message); 82 return; 83 } 84 85 if (isHeartbeatMessage(e.message)) { 86 console.log('onKeyMessage - heartbeat', e); 87 e.target.receivedHeartbeat = true; 88 verifyHeartbeatMessage(e); 89 return; 90 } 91 92 // No tested key system returns defaultURL in for key request messages. 93 if (e.defaultURL) { 94 failTest('keymessage unexpectedly has defaultURL: ' + e.defaultURL); 95 return; 96 } 97 98 // keymessage in response to generateKeyRequest. Reply with key. 99 console.log('onKeyMessage - key request', e); 100 var initData = e.message; 101 if (mediaType.indexOf('mp4') != -1) 102 initData = KEY_ID; // Temporary hack for Clear Key in v0.1. 103 video.webkitAddKey(keySystem, key, initData); 104 } 105 106 function verifyHeartbeatMessage(e) { 107 // Only External Clear Key sends a HEARTBEAT message. 108 if (e.keySystem != EXTERNAL_CLEAR_KEY_KEY_SYSTEM) { 109 failTest('Unexpected heartbeat from ' + e.keySystem); 110 return; 111 } 112 113 if (e.defaultURL != EXTERNAL_CLEAR_KEY_HEARTBEAT_URL) { 114 failTest('Heartbeat message with unexpected defaultURL: ' + e.defaultURL); 115 return; 116 } 117 } 118 119 video.addEventListener('webkitneedkey', onNeedKey); 120 video.addEventListener('webkitkeymessage', onKeyMessage); 121 video.addEventListener('webkitkeyerror', function() { 122 setResultInTitle("KeyError"); 123 }); 124 video.addEventListener('webkitkeyadded', onKeyAdded); 125 installTitleEventHandler(video, 'error'); 126 127 if (useMSE) { 128 var mediaSource = loadMediaSource(mediaFile, mediaType, 129 appendSourceCallbackFn); 130 video.src = window.URL.createObjectURL(mediaSource); 131 } else { 132 video.src = mediaFile; 133 } 134 } 135 136 function getInitDataFromKeyId(keyID) { 137 var init_key_id = new Uint8Array(keyID.length); 138 for(var i = 0; i < keyID.length; i++) { 139 init_key_id[i] = keyID.charCodeAt(i); 140 } 141 return init_key_id; 142 } 143