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