| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 // Utils provide logging functions and other JS functions commonly used by the | |
| 6 // app and media players. | |
| 7 var Utils = new function() { | |
| 8 this.titleChanged = false; | |
| 9 }; | |
| 10 | |
| 11 // Adds options to document element. | |
| 12 Utils.addOptions = function(elementID, keyValueOptions, disabledOptions) { | |
| 13 disabledOptions = disabledOptions || []; | |
| 14 var selectElement = document.getElementById(elementID); | |
| 15 var keys = Object.keys(keyValueOptions); | |
| 16 for (var i = 0; i < keys.length; i++) { | |
| 17 var key = keys[i]; | |
| 18 var option = new Option(key, keyValueOptions[key]); | |
| 19 option.title = keyValueOptions[key]; | |
| 20 if (disabledOptions.indexOf(key) >= 0) | |
| 21 option.disabled = true; | |
| 22 selectElement.options.add(option); | |
| 23 } | |
| 24 }; | |
| 25 | |
| 26 Utils.convertToArray = function(input) { | |
| 27 if (Array.isArray(input)) | |
| 28 return input; | |
| 29 return [input]; | |
| 30 }; | |
| 31 | |
| 32 Utils.convertToUint8Array = function(msg) { | |
| 33 var ans = new Uint8Array(msg.length); | |
| 34 for (var i = 0; i < msg.length; i++) { | |
| 35 ans[i] = msg.charCodeAt(i); | |
| 36 } | |
| 37 return ans; | |
| 38 }; | |
| 39 | |
| 40 Utils.createJWKData = function(keyId, key) { | |
| 41 // JWK routines copied from third_party/WebKit/LayoutTests/media/ | |
| 42 // encrypted-media/encrypted-media-utils.js | |
| 43 // | |
| 44 // Encodes data (Uint8Array) into base64 string without trailing '='. | |
| 45 // TODO(jrummell): Update once the EME spec is updated to say base64url | |
| 46 // encoding. | |
| 47 function base64Encode(data) { | |
| 48 var result = btoa(String.fromCharCode.apply(null, data)); | |
| 49 return result.replace(/=+$/g, ''); | |
| 50 } | |
| 51 | |
| 52 // Creates a JWK from raw key ID and key. | |
| 53 function createJWK(keyId, key) { | |
| 54 var jwk = '{"kty":"oct","kid":"'; | |
| 55 jwk += base64Encode(keyId); | |
| 56 jwk += '","k":"'; | |
| 57 jwk += base64Encode(key); | |
| 58 jwk += '"}'; | |
| 59 return jwk; | |
| 60 } | |
| 61 | |
| 62 // Creates a JWK Set from an array of JWK(s). | |
| 63 function createJWKSet() { | |
| 64 var jwkSet = '{"keys":['; | |
| 65 for (var i = 0; i < arguments.length; i++) { | |
| 66 if (i != 0) | |
| 67 jwkSet += ','; | |
| 68 jwkSet += arguments[i]; | |
| 69 } | |
| 70 jwkSet += ']}'; | |
| 71 return jwkSet; | |
| 72 } | |
| 73 | |
| 74 return Utils.convertToUint8Array(createJWKSet(createJWK(keyId, key))); | |
| 75 }; | |
| 76 | |
| 77 Utils.documentLog = function(log, success, time) { | |
| 78 if (!docLogs) | |
| 79 return; | |
| 80 time = time || Utils.getCurrentTimeString(); | |
| 81 var timeLog = '<span style="color: green">' + time + '</span>'; | |
| 82 var logColor = !success ? 'red' : 'black'; // default is true. | |
| 83 log = '<span style="color: "' + logColor + '>' + log + '</span>'; | |
| 84 docLogs.innerHTML = timeLog + ' - ' + log + '<br>' + docLogs.innerHTML; | |
| 85 }; | |
| 86 | |
| 87 Utils.ensureOptionInList = function(listID, option) { | |
| 88 var selectElement = document.getElementById(listID); | |
| 89 for (var i = 0; i < selectElement.length; i++) { | |
| 90 if (selectElement.options[i].value == option) { | |
| 91 selectElement.value = option; | |
| 92 return; | |
| 93 } | |
| 94 } | |
| 95 // The list does not have the option, let's add it and select it. | |
| 96 var optionElement = new Option(option, option); | |
| 97 optionElement.title = option; | |
| 98 selectElement.options.add(optionElement); | |
| 99 selectElement.value = option; | |
| 100 }; | |
| 101 | |
| 102 Utils.failTest = function(msg, newTitle) { | |
| 103 var failMessage = 'FAIL: '; | |
| 104 var title = 'FAILED'; | |
| 105 // Handle exception messages; | |
| 106 if (msg.message) { | |
| 107 title = msg.name || 'Error'; | |
| 108 failMessage += title + ' ' + msg.message; | |
| 109 } else if (msg instanceof Event) { | |
| 110 // Handle failing events. | |
| 111 failMessage = msg.target + '.' + msg.type; | |
| 112 title = msg.type; | |
| 113 } else { | |
| 114 failMessage += msg; | |
| 115 } | |
| 116 // Force newTitle if passed. | |
| 117 title = newTitle || title; | |
| 118 // Log failure. | |
| 119 Utils.documentLog(failMessage, false); | |
| 120 console.log(failMessage, msg); | |
| 121 Utils.setResultInTitle(title); | |
| 122 }; | |
| 123 | |
| 124 Utils.getCurrentTimeString = function() { | |
| 125 var date = new Date(); | |
| 126 var hours = ('0' + date.getHours()).slice(-2); | |
| 127 var minutes = ('0' + date.getMinutes()).slice(-2); | |
| 128 var secs = ('0' + date.getSeconds()).slice(-2); | |
| 129 var milliSecs = ('00' + date.getMilliseconds()).slice(-3); | |
| 130 return hours + ':' + minutes + ':' + secs + '.' + milliSecs; | |
| 131 }; | |
| 132 | |
| 133 Utils.getDefaultKey = function(forceInvalidResponse) { | |
| 134 if (forceInvalidResponse) { | |
| 135 Utils.timeLog('Forcing invalid key data.'); | |
| 136 return new Uint8Array([0xAA]); | |
| 137 } | |
| 138 return KEY; | |
| 139 }; | |
| 140 | |
| 141 Utils.getHexString = function(uintArray) { | |
| 142 var hex_str = ''; | |
| 143 for (var i = 0; i < uintArray.length; i++) { | |
| 144 var hex = uintArray[i].toString(16); | |
| 145 if (hex.length == 1) | |
| 146 hex = '0' + hex; | |
| 147 hex_str += hex; | |
| 148 } | |
| 149 return hex_str; | |
| 150 }; | |
| 151 | |
| 152 Utils.getInitDataFromMessage = function(message, mediaType) { | |
| 153 var initData = message.message; | |
| 154 if (mediaType.indexOf('mp4') != -1) { | |
| 155 // Temporary hack for Clear Key in v0.1. | |
| 156 // If content uses mp4, then message.message is PSSH data. Instead of | |
| 157 // parsing that data we hard code the initData. | |
| 158 initData = Utils.convertToUint8Array(KEY_ID); | |
| 159 } | |
| 160 return initData; | |
| 161 }; | |
| 162 | |
| 163 Utils.hasPrefix = function(msg, prefix) { | |
| 164 var message = String.fromCharCode.apply(null, msg); | |
| 165 return message.substring(0, prefix.length) == prefix; | |
| 166 }; | |
| 167 | |
| 168 Utils.installTitleEventHandler = function(element, event) { | |
| 169 element.addEventListener(event, function(e) { | |
| 170 Utils.setResultInTitle(e.type); | |
| 171 }, false); | |
| 172 }; | |
| 173 | |
| 174 Utils.isHeartBeatMessage = function(msg) { | |
| 175 return Utils.hasPrefix(msg, HEART_BEAT_HEADER); | |
| 176 }; | |
| 177 | |
| 178 Utils.resetTitleChange = function() { | |
| 179 this.titleChanged = false; | |
| 180 document.title = ''; | |
| 181 }; | |
| 182 | |
| 183 Utils.sendRequest = function(requestType, responseType, message, serverURL, | |
| 184 onSuccessCallbackFn, forceInvalidResponse) { | |
| 185 var requestAttemptCount = 0; | |
| 186 var MAXIMUM_REQUEST_ATTEMPTS = 3; | |
| 187 var REQUEST_RETRY_DELAY_MS = 3000; | |
| 188 | |
| 189 function sendRequestAttempt() { | |
| 190 requestAttemptCount++; | |
| 191 if (requestAttemptCount == MAXIMUM_REQUEST_ATTEMPTS) { | |
| 192 Utils.failTest('FAILED: Exceeded maximum license request attempts.'); | |
| 193 return; | |
| 194 } | |
| 195 var xmlhttp = new XMLHttpRequest(); | |
| 196 xmlhttp.responseType = responseType; | |
| 197 xmlhttp.open(requestType, serverURL, true); | |
| 198 | |
| 199 xmlhttp.onload = function(e) { | |
| 200 if (this.status == 200) { | |
| 201 if (onSuccessCallbackFn) | |
| 202 onSuccessCallbackFn(this.response); | |
| 203 } else { | |
| 204 Utils.timeLog('Bad response status: ' + this.status); | |
| 205 Utils.timeLog('Bad response: ' + this.response); | |
| 206 Utils.timeLog('Retrying request if possible in ' + | |
| 207 REQUEST_RETRY_DELAY_MS + 'ms'); | |
| 208 setTimeout(sendRequestAttempt, REQUEST_RETRY_DELAY_MS); | |
| 209 } | |
| 210 }; | |
| 211 Utils.timeLog('Attempt (' + requestAttemptCount + | |
| 212 '): sending request to server: ' + serverURL); | |
| 213 xmlhttp.send(message); | |
| 214 } | |
| 215 | |
| 216 if (forceInvalidResponse) { | |
| 217 Utils.timeLog('Not sending request - forcing an invalid response.'); | |
| 218 return onSuccessCallbackFn([0xAA]); | |
| 219 } | |
| 220 sendRequestAttempt(); | |
| 221 }; | |
| 222 | |
| 223 Utils.setResultInTitle = function(title) { | |
| 224 // If document title is 'ENDED', then update it with new title to possibly | |
| 225 // mark a test as failure. Otherwise, keep the first title change in place. | |
| 226 if (!this.titleChanged || document.title.toUpperCase() == 'ENDED') | |
| 227 document.title = title.toUpperCase(); | |
| 228 Utils.timeLog('Set document title to: ' + title + ', updated title: ' + | |
| 229 document.title); | |
| 230 this.titleChanged = true; | |
| 231 }; | |
| 232 | |
| 233 Utils.timeLog = function(/**/) { | |
| 234 if (arguments.length == 0) | |
| 235 return; | |
| 236 var time = Utils.getCurrentTimeString(); | |
| 237 // Log to document. | |
| 238 Utils.documentLog(arguments[0], time); | |
| 239 // Log to JS console. | |
| 240 var logString = time + ' - '; | |
| 241 for (var i = 0; i < arguments.length; i++) { | |
| 242 logString += ' ' + arguments[i]; | |
| 243 } | |
| 244 console.log(logString); | |
| 245 }; | |
| OLD | NEW |