15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivar sendRequestNatives = requireNative('sendRequest'); 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)function registerHooks(api) { 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var chromeTest = api.compiledApi; 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var apiFunctions = api.apiFunctions; 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) apiFunctions.setHandleRequest('notifyPass', function() { 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci requireAsync('testNatives').then(function(natives) { 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) natives.NotifyPass(); 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) apiFunctions.setHandleRequest('notifyFail', function(message) { 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci requireAsync('testNatives').then(function(natives) { 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) natives.NotifyFail(message); 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) apiFunctions.setHandleRequest('log', function() { 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci requireAsync('testNatives').then(function(natives) { 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) natives.Log($Array.join(arguments, ' ')); 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)function testDone(runNextTest) { 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Use a promise here to allow previous test contexts to be eligible for 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // garbage collection. 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Promise.resolve().then(function() { 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) runNextTest(); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)function exportTests(tests, runTests, exports) { 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) $Array.forEach(tests, function(test) { 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exports[test.name] = function() { 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) runTests([test]); 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * A fake implementation of setTimeout and clearTimeout. 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @constructor 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifunction TimeoutManager() { 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.timeouts_ = {}; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.nextTimeoutId_ = 0; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.currentTime = 0; 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.autorunEnabled_ = false; 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Installs setTimeout and clearTimeout into the global object. 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeoutManager.prototype.installGlobals = function() { 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var global = sendRequestNatives.GetGlobal({}); 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci global.setTimeout = this.setTimeout_.bind(this); 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci global.clearTimeout = this.clearTimeout_.bind(this); 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Starts auto-running of timeout callbacks. Until |numCallbacksToRun| callbacks 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * have run, any timeout callbacks set by calls to setTimeout (including before 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * the call to run) will cause the currentTime to be advanced to the time of 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * the timeout. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeoutManager.prototype.run = function(numCallbacksToRun) { 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.numCallbacksToRun_ = numCallbacksToRun; 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Promise.resolve().then(this.autoRun_.bind(this)); 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Runs timeout callbacks with earliest timeout. 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeoutManager.prototype.autoRun_ = function() { 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (this.numCallbacksToRun_ <= 0 || $Object.keys(this.timeouts_).length == 0) 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Bucket the timeouts by their timeout time. 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var timeoutsByTimeout = {}; 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var timeoutIds = $Object.keys(this.timeouts_); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (var i = 0; i < timeoutIds.length; i++) { 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var timeout = this.timeouts_[timeoutIds[i]]; 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var timeMs = timeout.timeMs; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!timeoutsByTimeout[timeMs]) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeoutsByTimeout[timeMs] = []; 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeoutsByTimeout[timeMs].push(timeout); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.currentTime = 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci $Function.apply(Math.min, null, $Object.keys((timeoutsByTimeout))); 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Run all timeouts in the earliest timeout bucket. 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var timeouts = timeoutsByTimeout[this.currentTime]; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (var i = 0; i < timeouts.length; i++) { 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var currentTimeout = timeouts[i]; 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!this.timeouts_[currentTimeout.id]) 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.numCallbacksToRun_--; 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delete this.timeouts_[currentTimeout.id]; 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try { 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci currentTimeout.target(); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } catch (e) { 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci console.log('error calling timeout target ' + e.stack); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Continue running any later callbacks. 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Promise.resolve().then(this.autoRun_.bind(this)); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * A fake implementation of setTimeout. This does not support passing callback 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * arguments. 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeoutManager.prototype.setTimeout_ = function(target, timeoutMs) { 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var timeoutId = this.nextTimeoutId_++; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.timeouts_[timeoutId] = { 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci id: timeoutId, 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci target: target, 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeMs: timeoutMs + this.currentTime, 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (this.autorunEnabled_) 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Promise.resolve().then(this.autoRun_.bind(this)); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return timeoutId; 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * A fake implementation of clearTimeout. 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeoutManager.prototype.clearTimeout_ = function(timeoutId) { 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (this.timeouts_[timeoutId]) 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delete this.timeouts_[timeoutId]; 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)exports.registerHooks = registerHooks; 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)exports.testDone = testDone; 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)exports.exportTests = exportTests; 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciexports.TimeoutManager = TimeoutManager; 147