190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var keySystem = QueryString.keysystem; 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var mediaFile = QueryString.mediafile; 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvar mediaType = QueryString.mediatype || 'video/webm; codecs="vorbis, vp8"'; 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvar useMSE = QueryString.usemse == 1; 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default key used to encrypt many media files used in browser tests. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var KEY = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// KEY_ID constant used as init data while encrypting test media files. 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var KEY_ID = getInitDataFromKeyId("0123456789012345"); 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Heart beat message header. 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var HEART_BEAT_HEADER = 'HEARTBEAT'; 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var EXTERNAL_CLEAR_KEY_KEY_SYSTEM = "org.chromium.externalclearkey"; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note that his URL has been normalized from the one in clear_key_cdm.cc. 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var EXTERNAL_CLEAR_KEY_HEARTBEAT_URL = 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'http://test.externalclearkey.chromium.org/'; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function isHeartbeatMessage(msg) { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (msg.length < HEART_BEAT_HEADER.length) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (var i = 0; i < HEART_BEAT_HEADER.length; ++i) { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (String.fromCharCode(msg[i]) != HEART_BEAT_HEADER[i]) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function loadEncryptedMediaFromURL(video) { 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return loadEncryptedMedia(video, mediaFile, keySystem, KEY, useMSE); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfunction loadEncryptedMedia(video, mediaFile, keySystem, key, useMSE, 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch appendSourceCallbackFn) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var keyRequested = false; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sourceOpened = false; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add properties to enable verification that events occurred. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video.receivedKeyAdded = false; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video.receivedHeartbeat = false; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video.isHeartbeatExpected = keySystem === EXTERNAL_CLEAR_KEY_KEY_SYSTEM; 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video.receivedKeyMessage = false; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!(video && mediaFile && keySystem && key)) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) failTest('Missing parameters in loadEncryptedMedia().'); 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function onNeedKey(e) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keyRequested) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyRequested = true; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.log('onNeedKey', e); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video.webkitGenerateKeyRequest(keySystem, e.initData); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) catch(error) { 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) setResultInTitle(error.name); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) function onKeyAdded(e) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) e.target.receivedKeyAdded = true; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function onKeyMessage(e) { 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video.receivedKeyMessage = true; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!e.keySystem || e.keySystem != keySystem) { 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) failTest('keymessage with unexpected keySystem: ' + e.keySystem); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!e.sessionId) { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) failTest('keymessage without a sessionId: ' + e.sessionId); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!e.message) { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) failTest('keymessage without a message: ' + e.message); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (isHeartbeatMessage(e.message)) { 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) console.log('onKeyMessage - heartbeat', e); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) e.target.receivedHeartbeat = true; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verifyHeartbeatMessage(e); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No tested key system returns defaultURL in for key request messages. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (e.defaultURL) { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) failTest('keymessage unexpectedly has defaultURL: ' + e.defaultURL); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // keymessage in response to generateKeyRequest. Reply with key. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) console.log('onKeyMessage - key request', e); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var initData = e.message; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mediaType.indexOf('mp4') != -1) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initData = KEY_ID; // Temporary hack for Clear Key in v0.1. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video.webkitAddKey(keySystem, key, initData); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) function verifyHeartbeatMessage(e) { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only External Clear Key sends a HEARTBEAT message. 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (e.keySystem != EXTERNAL_CLEAR_KEY_KEY_SYSTEM) { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) failTest('Unexpected heartbeat from ' + e.keySystem); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (e.defaultURL != EXTERNAL_CLEAR_KEY_HEARTBEAT_URL) { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) failTest('Heartbeat message with unexpected defaultURL: ' + e.defaultURL); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video.addEventListener('webkitneedkey', onNeedKey); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video.addEventListener('webkitkeymessage', onKeyMessage); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video.addEventListener('webkitkeyerror', function() { 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) setResultInTitle("KeyError"); 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video.addEventListener('webkitkeyadded', onKeyAdded); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installTitleEventHandler(video, 'error'); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (useMSE) { 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var mediaSource = loadMediaSource(mediaFile, mediaType, 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch appendSourceCallbackFn); 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch video.src = window.URL.createObjectURL(mediaSource); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch video.src = mediaFile; 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)function getInitDataFromKeyId(keyID) { 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var init_key_id = new Uint8Array(keyID.length); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for(var i = 0; i < keyID.length; i++) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) init_key_id[i] = keyID.charCodeAt(i); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return init_key_id; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 143