1 <html><head> 2 <meta http-equiv="Pragma" content="no-cache" /> 3 <meta http-equiv="Expires" content="-1" /> 4 <link rel="stylesheet" href="test_page.css"> 5 <script> 6 function AdjustHeight(frameWin) { 7 var div = frameWin.document.getElementsByTagName("div")[0]; 8 var height = frameWin.getComputedStyle(div).height; 9 frameWin.frameElement.style.height = height; 10 } 11 12 // Called when the tests are completed. |result| should be "PASS" if the test(s) 13 // passed, or information about the failure if the test(s) did not pass. 14 function DidExecuteTests(result) { 15 var plugin = document.getElementById("plugin"); 16 if (plugin.parentNode.removePlugin) { 17 plugin.parentNode.removeChild(plugin); 18 plugin = undefined; 19 } 20 if (CheckPostConditions()) 21 sendAutomationMessage(result); 22 23 if (window == top) 24 return; 25 26 // Otherwise, we are in a subframe, so we can use this opportunity to resize 27 // ourselves. 28 AdjustHeight(window); 29 } 30 31 function AppendFrame(testcase, i) { 32 var p = document.createElement("P"); 33 p.setAttribute("class", "frame-container"); 34 35 var title = document.createElement("H2"); 36 title.appendChild(document.createTextNode(testcase)); 37 p.appendChild(title); 38 39 var frame = document.createElement("IFRAME"); 40 var mode = ExtractSearchParameter("mode"); 41 var websocket_host = ExtractSearchParameter("websocket_host"); 42 var websocket_port = ExtractSearchParameter("websocket_port"); 43 var ssl_server_port = ExtractSearchParameter("ssl_server_port"); 44 var src = "?testcase=" + testcase; 45 if (mode == "nacl") 46 src += "&mode=nacl"; 47 if (websocket_host != "") 48 src += "&websocket_host=" + websocket_host; 49 if (websocket_port != "") 50 src += "&websocket_port=" + websocket_port; 51 if (ssl_server_port != "") 52 src += "&ssl_server_port=" + ssl_server_port; 53 frame.setAttribute("src", src); 54 55 frame.setAttribute("onload", "LoadNext(" + (i + 1) + ")"); 56 p.appendChild(frame); 57 58 document.body.appendChild(p); 59 } 60 61 function LoadNext(i) { 62 var links = document.links; 63 if (links.length > i) 64 AppendFrame(links[i].firstChild.nodeValue, i); 65 } 66 67 function RunAll() { 68 // Remove any existing frames. 69 var existing = document.getElementsByClassName("frame-container"); 70 while (existing.length) 71 existing[0].parentNode.removeChild(existing[0]); 72 73 // Add new frames for each test, but do so one frame at a time. 74 LoadNext(0); 75 } 76 77 function ExtractSearchParameter(name) { 78 var nameIndex = location.search.indexOf(name + "="); 79 if (nameIndex != -1) { 80 var value = location.search.substring(nameIndex + name.length + 1); 81 var endIndex = value.indexOf("&"); 82 if (endIndex != -1) 83 value = value.substring(0, endIndex); 84 return value; 85 } 86 return ""; 87 } 88 89 // Parses the message, looking for strings of the form: 90 // TESTING_MESSAGE:<message_type>:<message_contents> 91 // 92 // If the message_data is not a string or does not match the above format, then 93 // undefined is returned. 94 // 95 // Otherwise, returns an array containing 2 items. The 0th element is the 96 // message_type, one of: 97 // - AddPostCondition 98 // - ClearConsole 99 // - DidExecuteTests 100 // - EvalScript 101 // - LogHTML 102 // - RemovePluginWhenFinished 103 // - ReportProgress 104 // The second item is the verbatim message_contents. 105 function ParseTestingMessage(message_data) { 106 if (typeof(message_data) != "string") 107 return undefined; 108 var testing_message_prefix = "TESTING_MESSAGE"; 109 var delim_str = ":"; 110 var delim1 = message_data.indexOf(delim_str); 111 if (message_data.substring(0, delim1) !== testing_message_prefix) 112 return undefined; 113 var delim2 = message_data.indexOf(delim_str, delim1 + 1); 114 if (delim2 == -1) 115 delim2 = message_data.length; 116 var message_type = message_data.substring(delim1 + 1, delim2); 117 var message_contents = message_data.substring(delim2 + 1); 118 return [message_type, message_contents]; 119 } 120 121 function ClearConsole() { 122 window.document.getElementById("console").innerHTML = ""; 123 } 124 125 function LogHTML(html) { 126 window.document.getElementById("console").innerHTML += html; 127 } 128 129 function RemovePluginWhenFinished() { 130 window.document.getElementById("container").removePlugin = true; 131 } 132 133 function sendAutomationMessage(msg) { 134 if (window.domAutomationController) { 135 window.domAutomationController.setAutomationId(0); 136 window.domAutomationController.send(msg); 137 } 138 } 139 140 function LogTestTime(test_time) { 141 console.log(test_time); 142 } 143 144 // If something goes really wrong, the test running inside the plugin may not 145 // terminate. For example, if the plugin does not load, the test will never 146 // send "PASS" to the browser. In this case we should explicitly use the 147 // automation controller to terminate the test. 148 function InternalError(msg) { 149 LogHTML("<p>" + msg); 150 sendAutomationMessage(msg); 151 } 152 153 function EvalScript(script) { 154 try { 155 eval(script); 156 } catch(ex) { 157 } 158 } 159 160 var conditions = []; 161 // Add a "PostCondition". These are bits of script that are run after the plugin 162 // is destroyed. If they evaluate to false or throw an exception, it's 163 // considered a failure. 164 function AddPostCondition(script) { 165 conditions.push(script); 166 } 167 // Update the HTML to show the failure and update cookies so that ui_tests 168 // doesn't count this as a pass. 169 function ConditionFailed(error) { 170 error_string = "Post condition check failed: " + error; 171 InternalError(error_string); 172 } 173 // Iterate through the post conditions defined in |conditions| and check that 174 // they all pass. 175 function CheckPostConditions() { 176 var success = true; 177 for (var i = 0; i < conditions.length; ++i) { 178 var script = conditions[i]; 179 try { 180 if (!eval(script)) { 181 ConditionFailed("\"" + script + "\""); 182 success = false; 183 } 184 } catch (ex) { 185 ConditionFailed("\"" + script + "\"" + " failed with exception: " + 186 "\"" + ex.toString() + "\""); 187 success = false; 188 } 189 } 190 return success; 191 } 192 193 function IsTestingMessage(message_data) { 194 return (ParseTestingMessage(message_data) != undefined); 195 } 196 197 function handleTestingMessage(message_event) { 198 var type_contents_tuple = ParseTestingMessage(message_event.data); 199 if (type_contents_tuple) { 200 var type = type_contents_tuple[0]; 201 var contents = type_contents_tuple[1]; 202 if (type === "AddPostCondition") 203 AddPostCondition(contents); 204 else if (type === "ClearConsole") 205 ClearConsole(); 206 else if (type === "DidExecuteTests") 207 DidExecuteTests(contents); 208 else if (type === "EvalScript") 209 EvalScript(contents); 210 else if (type === "LogHTML") 211 LogHTML(contents); 212 else if (type === "RemovePluginWhenFinished") 213 RemovePluginWhenFinished(); 214 else if (type === "ReportProgress") 215 sendAutomationMessage(contents); 216 else if (type === "LogTestTime") 217 LogTestTime(contents); 218 } 219 } 220 221 function sendProgress() { 222 // We send "..." to signal that we're still working. See 223 // ppapi/tests/testing_instance.h for how this works. 224 sendAutomationMessage("..."); 225 } 226 227 onload = function() { 228 var testcase = ExtractSearchParameter("testcase"); 229 var mode = ExtractSearchParameter("mode"); 230 document.title = 'Test ' + testcase; 231 var obj; 232 if (mode == "nacl_newlib") { 233 obj = document.createElement("EMBED"); 234 obj.setAttribute("src", "ppapi_nacl_tests_newlib.nmf"); 235 obj.setAttribute("type", "application/x-nacl"); 236 obj.setAttribute("mode", mode); 237 } else if (mode == "nacl_glibc") { 238 obj = document.createElement("EMBED"); 239 obj.setAttribute("src", "ppapi_nacl_tests_glibc.nmf"); 240 obj.setAttribute("type", "application/x-nacl"); 241 obj.setAttribute("mode", mode); 242 } else if (mode == "nacl_pnacl") { 243 obj = document.createElement("EMBED"); 244 obj.setAttribute("src", "ppapi_nacl_tests_pnacl.nmf"); 245 obj.setAttribute("type", "application/x-nacl"); 246 obj.setAttribute("mode", mode); 247 } else { 248 var mimeType = "application/x-ppapi-tests"; 249 if (mimeType in navigator.mimeTypes) { 250 obj = document.createElement("EMBED"); 251 obj.setAttribute("src", "http://a.b.c/test"); 252 obj.setAttribute("type", mimeType); 253 } else { 254 document.getElementById("console").innerHTML = 255 '<span class="fail">FAIL</span>: ' + 256 '<span class="err_msg">Test plug-in is not registered.</span>'; 257 } 258 } 259 if (obj) { 260 obj.setAttribute("width", 80); 261 obj.setAttribute("height", 80); 262 obj.setAttribute("style", 263 "background-color:#AAAAAA;border:1px solid black;"); 264 obj.setAttribute("id", "plugin"); 265 obj.setAttribute("testcase", testcase); 266 obj.setAttribute("protocol", window.location.protocol); 267 var websocket_host = ExtractSearchParameter("websocket_host"); 268 if (websocket_host != "") 269 obj.setAttribute("websocket_host", websocket_host); 270 var websocket_port = ExtractSearchParameter("websocket_port"); 271 if (websocket_port != "") 272 obj.setAttribute("websocket_port", websocket_port); 273 var ssl_server_port = ExtractSearchParameter("ssl_server_port"); 274 if (ssl_server_port != "") 275 obj.setAttribute("ssl_server_port", ssl_server_port); 276 277 var container = document.getElementById("container"); 278 container.addEventListener("message", handleTestingMessage, true); 279 280 // "error" and "crash" events will only fire for NaCl, but adding these 281 // listeners doesn't hurt in the non-NaCl cases. 282 obj.addEventListener("error", function() { 283 InternalError("Plugin did not load. '" + obj.lastError + "'"); 284 }, true); 285 obj.addEventListener("crash", function() { 286 InternalError("Plugin crashed. '" + obj.lastError + "'"); 287 }, true); 288 289 // NaCl sends progress events while loading. When we get one, notify the 290 // domAutomationController so that it knows we're still working. 291 obj.addEventListener("loadstart", sendProgress, true); 292 obj.addEventListener("progress", sendProgress, true); 293 obj.addEventListener("load", sendProgress, true); 294 obj.addEventListener("loadend", sendProgress, true); 295 296 // Register a bad dispatchEvent to make sure it isn't used. See 'EVIL' note 297 // below. 298 var original = obj.dispatchEvent; 299 obj.dispatchEvent = function() { 300 InternalError("Bad dispatchEvent called!"); 301 } 302 container.appendChild(obj); 303 } 304 } 305 306 // EVIL Note: 307 // This part of the script does some nefarious things to make sure that it 308 // doesn't affect the behavior of PostMessage (on which all the tests rely). In 309 // particular, we replace document.createEvent, MessageEvent.initMessageEvent, 310 // and the MessageEvent constructor. Previously, the NaCl integration 311 // implementation made use of these and would fail (http://crbug.com/82604 312 // and http://crbug.com/109775). 313 document.createEvent = function() { 314 InternalError("Bad document.createEvent called!"); 315 } 316 function MessageEvent() { 317 InternalError("Bad MessageEvent constructor called!"); 318 } 319 MessageEvent.prototype.initMessageEvent = function() { 320 InternalError("Bad MessageEvent.initMessageEvent called!"); 321 } 322 323 </script> 324 </head><body> 325 <div> 326 <div id="container"></div> 327 <div id="console"><span class="load_msg">loading...</span></div> 328 </div> 329 </body></html> 330