1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/media/tests/mochitest/head.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,260 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +var Cc = SpecialPowers.Cc; 1.9 +var Ci = SpecialPowers.Ci; 1.10 +var Cr = SpecialPowers.Cr; 1.11 + 1.12 +// Specifies whether we are using fake streams to run this automation 1.13 +var FAKE_ENABLED = true; 1.14 + 1.15 + 1.16 +/** 1.17 + * Create the necessary HTML elements for head and body as used by Mochitests 1.18 + * 1.19 + * @param {object} meta 1.20 + * Meta information of the test 1.21 + * @param {string} meta.title 1.22 + * Description of the test 1.23 + * @param {string} [meta.bug] 1.24 + * Bug the test was created for 1.25 + * @param {boolean} [meta.visible=false] 1.26 + * Visibility of the media elements 1.27 + */ 1.28 +function createHTML(meta) { 1.29 + var test = document.getElementById('test'); 1.30 + 1.31 + // Create the head content 1.32 + var elem = document.createElement('meta'); 1.33 + elem.setAttribute('charset', 'utf-8'); 1.34 + document.head.appendChild(elem); 1.35 + 1.36 + var title = document.createElement('title'); 1.37 + title.textContent = meta.title; 1.38 + document.head.appendChild(title); 1.39 + 1.40 + // Create the body content 1.41 + var anchor = document.createElement('a'); 1.42 + anchor.setAttribute('target', '_blank'); 1.43 + 1.44 + if (meta.bug) { 1.45 + anchor.setAttribute('href', 'https://bugzilla.mozilla.org/show_bug.cgi?id=' + meta.bug); 1.46 + } 1.47 + 1.48 + anchor.textContent = meta.title; 1.49 + document.body.insertBefore(anchor, test); 1.50 + 1.51 + var display = document.createElement('p'); 1.52 + display.setAttribute('id', 'display'); 1.53 + document.body.insertBefore(display, test); 1.54 + 1.55 + var content = document.createElement('div'); 1.56 + content.setAttribute('id', 'content'); 1.57 + content.style.display = meta.visible ? 'block' : "none"; 1.58 + document.body.appendChild(content); 1.59 +} 1.60 + 1.61 + 1.62 +/** 1.63 + * Create the HTML element if it doesn't exist yet and attach 1.64 + * it to the content node. 1.65 + * 1.66 + * @param {string} type 1.67 + * Type of media element to create ('audio' or 'video') 1.68 + * @param {string} label 1.69 + * Description to use for the element 1.70 + * @return {HTMLMediaElement} The created HTML media element 1.71 + */ 1.72 +function createMediaElement(type, label) { 1.73 + var id = label + '_' + type; 1.74 + var element = document.getElementById(id); 1.75 + 1.76 + // Sanity check that we haven't created the element already 1.77 + if (element) 1.78 + return element; 1.79 + 1.80 + element = document.createElement(type === 'audio' ? 'audio' : 'video'); 1.81 + element.setAttribute('id', id); 1.82 + element.setAttribute('height', 100); 1.83 + element.setAttribute('width', 150); 1.84 + element.setAttribute('controls', 'controls'); 1.85 + document.getElementById('content').appendChild(element); 1.86 + 1.87 + return element; 1.88 +} 1.89 + 1.90 + 1.91 +/** 1.92 + * Wrapper function for mozGetUserMedia to allow a singular area of control 1.93 + * for determining whether we run this with fake devices or not. 1.94 + * 1.95 + * @param {Dictionary} constraints 1.96 + * The constraints for this mozGetUserMedia callback 1.97 + * @param {Function} onSuccess 1.98 + * The success callback if the stream is successfully retrieved 1.99 + * @param {Function} onError 1.100 + * The error callback if the stream fails to be retrieved 1.101 + */ 1.102 +function getUserMedia(constraints, onSuccess, onError) { 1.103 + constraints["fake"] = FAKE_ENABLED; 1.104 + 1.105 + info("Call getUserMedia for " + JSON.stringify(constraints)); 1.106 + navigator.mozGetUserMedia(constraints, onSuccess, onError); 1.107 +} 1.108 + 1.109 + 1.110 +/** 1.111 + * Setup any Mochitest for WebRTC by enabling the preference for 1.112 + * peer connections. As by bug 797979 it will also enable mozGetUserMedia() 1.113 + * and disable the mozGetUserMedia() permission checking. 1.114 + * 1.115 + * @param {Function} aCallback 1.116 + * Test method to execute after initialization 1.117 + */ 1.118 +function runTest(aCallback) { 1.119 + if (window.SimpleTest) { 1.120 + // Running as a Mochitest. 1.121 + SimpleTest.waitForExplicitFinish(); 1.122 + SpecialPowers.pushPrefEnv({'set': [ 1.123 + ['dom.messageChannel.enabled', true], 1.124 + ['media.peerconnection.enabled', true], 1.125 + ['media.peerconnection.identity.enabled', true], 1.126 + ['media.peerconnection.identity.timeout', 12000], 1.127 + ['media.navigator.permission.disabled', true]] 1.128 + }, function () { 1.129 + try { 1.130 + aCallback(); 1.131 + } 1.132 + catch (err) { 1.133 + generateErrorCallback()(err); 1.134 + } 1.135 + }); 1.136 + } else { 1.137 + // Steeplechase, let it call the callback. 1.138 + window.run_test = function(is_initiator) { 1.139 + var options = {is_local: is_initiator, 1.140 + is_remote: !is_initiator}; 1.141 + aCallback(options); 1.142 + }; 1.143 + // Also load the steeplechase test code. 1.144 + var s = document.createElement("script"); 1.145 + s.src = "/test.js"; 1.146 + document.head.appendChild(s); 1.147 + } 1.148 +} 1.149 + 1.150 +/** 1.151 + * Checks that the media stream tracks have the expected amount of tracks 1.152 + * with the correct kind and id based on the type and constraints given. 1.153 + * 1.154 + * @param {Object} constraints specifies whether the stream should have 1.155 + * audio, video, or both 1.156 + * @param {String} type the type of media stream tracks being checked 1.157 + * @param {sequence<MediaStreamTrack>} mediaStreamTracks the media stream 1.158 + * tracks being checked 1.159 + */ 1.160 +function checkMediaStreamTracksByType(constraints, type, mediaStreamTracks) { 1.161 + if(constraints[type]) { 1.162 + is(mediaStreamTracks.length, 1, 'One ' + type + ' track shall be present'); 1.163 + 1.164 + if(mediaStreamTracks.length) { 1.165 + is(mediaStreamTracks[0].kind, type, 'Track kind should be ' + type); 1.166 + ok(mediaStreamTracks[0].id, 'Track id should be defined'); 1.167 + } 1.168 + } else { 1.169 + is(mediaStreamTracks.length, 0, 'No ' + type + ' tracks shall be present'); 1.170 + } 1.171 +} 1.172 + 1.173 +/** 1.174 + * Check that the given media stream contains the expected media stream 1.175 + * tracks given the associated audio & video constraints provided. 1.176 + * 1.177 + * @param {Object} constraints specifies whether the stream should have 1.178 + * audio, video, or both 1.179 + * @param {MediaStream} mediaStream the media stream being checked 1.180 + */ 1.181 +function checkMediaStreamTracks(constraints, mediaStream) { 1.182 + checkMediaStreamTracksByType(constraints, 'audio', 1.183 + mediaStream.getAudioTracks()); 1.184 + checkMediaStreamTracksByType(constraints, 'video', 1.185 + mediaStream.getVideoTracks()); 1.186 +} 1.187 + 1.188 +/** 1.189 + * Utility methods 1.190 + */ 1.191 + 1.192 +/** 1.193 + * Returns the contents of a blob as text 1.194 + * 1.195 + * @param {Blob} blob 1.196 + The blob to retrieve the contents from 1.197 + * @param {Function} onSuccess 1.198 + Callback with the blobs content as parameter 1.199 + */ 1.200 +function getBlobContent(blob, onSuccess) { 1.201 + var reader = new FileReader(); 1.202 + 1.203 + // Listen for 'onloadend' which will always be called after a success or failure 1.204 + reader.onloadend = function (event) { 1.205 + onSuccess(event.target.result); 1.206 + }; 1.207 + 1.208 + reader.readAsText(blob); 1.209 +} 1.210 + 1.211 +/** 1.212 + * Generates a callback function fired only under unexpected circumstances 1.213 + * while running the tests. The generated function kills off the test as well 1.214 + * gracefully. 1.215 + * 1.216 + * @param {String} [message] 1.217 + * An optional message to show if no object gets passed into the 1.218 + * generated callback method. 1.219 + */ 1.220 +function generateErrorCallback(message) { 1.221 + var stack = new Error().stack.split("\n"); 1.222 + stack.shift(); // Don't include this instantiation frame 1.223 + 1.224 + /** 1.225 + * @param {object} aObj 1.226 + * The object fired back from the callback 1.227 + */ 1.228 + return function (aObj) { 1.229 + if (aObj) { 1.230 + if (aObj.name && aObj.message) { 1.231 + ok(false, "Unexpected callback for '" + aObj.name + 1.232 + "' with message = '" + aObj.message + "' at " + 1.233 + JSON.stringify(stack)); 1.234 + } else { 1.235 + ok(false, "Unexpected callback with = '" + aObj + 1.236 + "' at: " + JSON.stringify(stack)); 1.237 + } 1.238 + } else { 1.239 + ok(false, "Unexpected callback with message = '" + message + 1.240 + "' at: " + JSON.stringify(stack)); 1.241 + } 1.242 + SimpleTest.finish(); 1.243 + } 1.244 +} 1.245 + 1.246 +/** 1.247 + * Generates a callback function fired only for unexpected events happening. 1.248 + * 1.249 + * @param {String} description 1.250 + Description of the object for which the event has been fired 1.251 + * @param {String} eventName 1.252 + Name of the unexpected event 1.253 + */ 1.254 +function unexpectedEventAndFinish(message, eventName) { 1.255 + var stack = new Error().stack.split("\n"); 1.256 + stack.shift(); // Don't include this instantiation frame 1.257 + 1.258 + return function () { 1.259 + ok(false, "Unexpected event '" + eventName + "' fired with message = '" + 1.260 + message + "' at: " + JSON.stringify(stack)); 1.261 + SimpleTest.finish(); 1.262 + } 1.263 +}