Home | History | Annotate | Download | only in media
      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