OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library browser; | 4 library browser; |
5 | 5 |
6 import "dart:async"; | 6 import "dart:async"; |
7 import "dart:convert" show UTF8, JSON; | 7 import "dart:convert" show UTF8, JSON; |
8 import "dart:core"; | 8 import "dart:core"; |
9 import "dart:io"; | 9 import "dart:io"; |
10 import "dart:math" show min; | 10 import "dart:math" show min; |
11 | 11 |
12 import 'android.dart'; | 12 import 'android.dart'; |
13 import 'http_server.dart'; | 13 import 'http_server.dart'; |
14 import 'path.dart'; | 14 import 'path.dart'; |
15 import 'utils.dart'; | 15 import 'utils.dart'; |
16 | 16 |
17 import 'reset_safari.dart' show | 17 import 'reset_safari.dart' show killAndResetSafari; |
18 killAndResetSafari; | |
19 | 18 |
20 class BrowserOutput { | 19 class BrowserOutput { |
21 final StringBuffer stdout = new StringBuffer(); | 20 final StringBuffer stdout = new StringBuffer(); |
22 final StringBuffer stderr = new StringBuffer(); | 21 final StringBuffer stderr = new StringBuffer(); |
23 final StringBuffer eventLog = new StringBuffer(); | 22 final StringBuffer eventLog = new StringBuffer(); |
24 } | 23 } |
25 | 24 |
26 /** Class describing the interface for communicating with browsers. */ | 25 /** Class describing the interface for communicating with browsers. */ |
27 abstract class Browser { | 26 abstract class Browser { |
28 BrowserOutput _allBrowserOutput = new BrowserOutput(); | 27 BrowserOutput _allBrowserOutput = new BrowserOutput(); |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 if (!Browser.resetBrowserConfiguration) return true; | 304 if (!Browser.resetBrowserConfiguration) return true; |
306 | 305 |
307 Completer completer = new Completer(); | 306 Completer completer = new Completer(); |
308 handleUncaughtError(error, StackTrace stackTrace) { | 307 handleUncaughtError(error, StackTrace stackTrace) { |
309 if (!completer.isCompleted) { | 308 if (!completer.isCompleted) { |
310 completer.completeError(error, stackTrace); | 309 completer.completeError(error, stackTrace); |
311 } else { | 310 } else { |
312 throw new AsyncError(error, stackTrace); | 311 throw new AsyncError(error, stackTrace); |
313 } | 312 } |
314 } | 313 } |
| 314 |
315 Zone parent = Zone.current; | 315 Zone parent = Zone.current; |
316 ZoneSpecification specification = new ZoneSpecification( | 316 ZoneSpecification specification = new ZoneSpecification( |
317 print: (Zone self, ZoneDelegate delegate, Zone zone, String line) { | 317 print: (Zone self, ZoneDelegate delegate, Zone zone, String line) { |
318 delegate.run(parent, () { | 318 delegate.run(parent, () { |
319 _logEvent(line); | 319 _logEvent(line); |
320 }); | 320 }); |
321 }); | 321 }); |
322 Future zoneWrapper() { | 322 Future zoneWrapper() { |
323 Uri safariUri = Uri.base.resolve(safariBundleLocation); | 323 Uri safariUri = Uri.base.resolve(safariBundleLocation); |
324 return new Future(() => killAndResetSafari(bundle: safariUri)) | 324 return new Future(() => killAndResetSafari(bundle: safariUri)) |
325 .then(completer.complete); | 325 .then(completer.complete); |
326 } | 326 } |
327 | 327 |
328 // We run killAndResetSafari in a Zone as opposed to running an external | 328 // We run killAndResetSafari in a Zone as opposed to running an external |
329 // process. The Zone allows us to collect its output, and protect the rest | 329 // process. The Zone allows us to collect its output, and protect the rest |
330 // of the test infrastructure against errors in it. | 330 // of the test infrastructure against errors in it. |
331 runZoned( | 331 runZoned(zoneWrapper, |
332 zoneWrapper, zoneSpecification: specification, | 332 zoneSpecification: specification, onError: handleUncaughtError); |
333 onError: handleUncaughtError); | |
334 | 333 |
335 try { | 334 try { |
336 await completer.future; | 335 await completer.future; |
337 return true; | 336 return true; |
338 } catch (error, st) { | 337 } catch (error, st) { |
339 _logEvent("Unable to reset Safari: $error$st"); | 338 _logEvent("Unable to reset Safari: $error$st"); |
340 return false; | 339 return false; |
341 } | 340 } |
342 } | 341 } |
343 | 342 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 _cleanup = () { | 405 _cleanup = () { |
407 userDir.deleteSync(recursive: true); | 406 userDir.deleteSync(recursive: true); |
408 }; | 407 }; |
409 try { | 408 try { |
410 await _createLaunchHTML(userDir.path, url); | 409 await _createLaunchHTML(userDir.path, url); |
411 } catch (error) { | 410 } catch (error) { |
412 _logEvent("Error creating launch HTML: $error"); | 411 _logEvent("Error creating launch HTML: $error"); |
413 return false; | 412 return false; |
414 } | 413 } |
415 var args = [ | 414 var args = [ |
416 "-d", "-i", "-m", "-s", "-u", _binary, | 415 "-d", |
417 "${userDir.path}/launch.html"]; | 416 "-i", |
| 417 "-m", |
| 418 "-s", |
| 419 "-u", |
| 420 _binary, |
| 421 "${userDir.path}/launch.html" |
| 422 ]; |
418 try { | 423 try { |
419 return startBrowserProcess("/usr/bin/caffeinate", args); | 424 return startBrowserProcess("/usr/bin/caffeinate", args); |
420 } catch (error) { | 425 } catch (error) { |
421 _logEvent("Error starting browser process: $error"); | 426 _logEvent("Error starting browser process: $error"); |
422 return false; | 427 return false; |
423 } | 428 } |
424 } | 429 } |
425 | 430 |
426 Future<Null> onDriverPageRequested() async { | 431 Future<Null> onDriverPageRequested() async { |
427 await Process.run("/usr/bin/osascript", | 432 await Process.run( |
428 ['-e', 'tell application "Safari" to activate']); | 433 "/usr/bin/osascript", ['-e', 'tell application "Safari" to activate']); |
429 } | 434 } |
430 | 435 |
431 String toString() => "Safari"; | 436 String toString() => "Safari"; |
432 } | 437 } |
433 | 438 |
434 class Chrome extends Browser { | 439 class Chrome extends Browser { |
435 String _version = "Version not found yet"; | 440 String _version = "Version not found yet"; |
436 | 441 |
437 Map<String, String> _getEnvironment() => null; | 442 Map<String, String> _getEnvironment() => null; |
438 | 443 |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 _logEvent("Failed to firefox get version"); | 797 _logEvent("Failed to firefox get version"); |
793 _logEvent("Make sure $_binary is a valid program for running firefox"); | 798 _logEvent("Make sure $_binary is a valid program for running firefox"); |
794 return new Future.value(false); | 799 return new Future.value(false); |
795 } | 800 } |
796 version = versionResult.stdout; | 801 version = versionResult.stdout; |
797 _logEvent("Got version: $version"); | 802 _logEvent("Got version: $version"); |
798 | 803 |
799 return Directory.systemTemp.createTemp().then((userDir) { | 804 return Directory.systemTemp.createTemp().then((userDir) { |
800 _createPreferenceFile(userDir.path); | 805 _createPreferenceFile(userDir.path); |
801 _cleanup = () { | 806 _cleanup = () { |
802 userDir.deleteSync(recursive: true); | 807 try { |
| 808 userDir.deleteSync(recursive: true); |
| 809 } catch (e) { |
| 810 _logEvent( |
| 811 "Error: failed to delete Chrome user-data-dir ${userDir.path}" |
| 812 ", will try again in 40 seconds: $e"); |
| 813 new Timer(new Duration(seconds: 40), () { |
| 814 try { |
| 815 userDir.deleteSync(recursive: true); |
| 816 } catch (e) { |
| 817 _logEvent("Error: failed on second attempt to delete Chrome " |
| 818 "user-data-dir ${userDir.path}: $e"); |
| 819 } |
| 820 }); |
| 821 } |
803 }; | 822 }; |
804 var args = [ | 823 var args = [ |
805 "-profile", | 824 "-profile", |
806 "${userDir.path}", | 825 "${userDir.path}", |
807 "-no-remote", | 826 "-no-remote", |
808 "-new-instance", | 827 "-new-instance", |
809 url | 828 url |
810 ]; | 829 ]; |
811 var environment = new Map<String, String>.from(Platform.environment); | 830 var environment = new Map<String, String>.from(Platform.environment); |
812 environment["MOZ_CRASHREPORTER_DISABLE"] = "1"; | 831 environment["MOZ_CRASHREPORTER_DISABLE"] = "1"; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 // When no browser is currently starting, _currentStartingBrowserId is null. | 983 // When no browser is currently starting, _currentStartingBrowserId is null. |
965 bool get aBrowserIsCurrentlyStarting => _currentStartingBrowserId != null; | 984 bool get aBrowserIsCurrentlyStarting => _currentStartingBrowserId != null; |
966 void markCurrentlyStarting(String id) { | 985 void markCurrentlyStarting(String id) { |
967 _currentStartingBrowserId = id; | 986 _currentStartingBrowserId = id; |
968 } | 987 } |
969 | 988 |
970 void markNotCurrentlyStarting(String id) { | 989 void markNotCurrentlyStarting(String id) { |
971 if (_currentStartingBrowserId == id) _currentStartingBrowserId = null; | 990 if (_currentStartingBrowserId == id) _currentStartingBrowserId = null; |
972 } | 991 } |
973 | 992 |
974 BrowserTestRunner( | 993 BrowserTestRunner(Map configuration, String localIp, String browserName, |
975 Map configuration, | |
976 String localIp, | |
977 String browserName, | |
978 this.maxNumBrowsers) | 994 this.maxNumBrowsers) |
979 : configuration = configuration, | 995 : configuration = configuration, |
980 localIp = localIp, | 996 localIp = localIp, |
981 browserName = (browserName == 'ff') ? 'firefox' : browserName, | 997 browserName = (browserName == 'ff') ? 'firefox' : browserName, |
982 checkedMode = configuration['checked'], | 998 checkedMode = configuration['checked'], |
983 testingServer = new BrowserTestingServer( | 999 testingServer = new BrowserTestingServer( |
984 configuration, localIp, | 1000 configuration, |
| 1001 localIp, |
985 Browser.requiresIframe(browserName), | 1002 Browser.requiresIframe(browserName), |
986 Browser.requiresFocus(browserName)) { | 1003 Browser.requiresFocus(browserName)) { |
987 testingServer.testRunner = this; | 1004 testingServer.testRunner = this; |
988 } | 1005 } |
989 | 1006 |
990 Future start() async { | 1007 Future start() async { |
991 await testingServer.start(); | 1008 await testingServer.start(); |
992 testingServer | 1009 testingServer |
993 ..testDoneCallBack = handleResults | 1010 ..testDoneCallBack = handleResults |
994 ..testStatusUpdateCallBack = handleStatusUpdate | 1011 ..testStatusUpdateCallBack = handleStatusUpdate |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 DebugLogger.error("Error getting error from browser" | 1386 DebugLogger.error("Error getting error from browser" |
1370 "on uri ${request.uri.path}: $error"); | 1387 "on uri ${request.uri.path}: $error"); |
1371 }); | 1388 }); |
1372 request.response.close(); | 1389 request.response.close(); |
1373 DebugLogger.error("Error from browser on : " | 1390 DebugLogger.error("Error from browser on : " |
1374 "${request.uri.path}, data: $back"); | 1391 "${request.uri.path}, data: $back"); |
1375 }, onError: (error) { | 1392 }, onError: (error) { |
1376 print(error); | 1393 print(error); |
1377 }); | 1394 }); |
1378 } | 1395 } |
| 1396 |
1379 void errorHandler(e) { | 1397 void errorHandler(e) { |
1380 if (!underTermination) print("Error occured in httpserver: $e"); | 1398 if (!underTermination) print("Error occured in httpserver: $e"); |
1381 } | 1399 } |
| 1400 |
1382 errorReportingServer.listen(errorReportingHandler, onError: errorHandler); | 1401 errorReportingServer.listen(errorReportingHandler, onError: errorHandler); |
1383 } | 1402 } |
1384 | 1403 |
1385 void setupDispatchingServer(_) { | 1404 void setupDispatchingServer(_) { |
1386 DispatchingServer server = configuration['_servers_'].server; | 1405 DispatchingServer server = configuration['_servers_'].server; |
1387 void noCache(request) { | 1406 void noCache(request) { |
1388 request.response.headers | 1407 request.response.headers |
1389 .set("Cache-Control", "no-cache, no-store, must-revalidate"); | 1408 .set("Cache-Control", "no-cache, no-store, must-revalidate"); |
1390 } | 1409 } |
| 1410 |
1391 int testId(request) => int.parse(request.uri.queryParameters["id"]); | 1411 int testId(request) => int.parse(request.uri.queryParameters["id"]); |
1392 String browserId(request, prefix) => | 1412 String browserId(request, prefix) => |
1393 request.uri.path.substring(prefix.length + 1); | 1413 request.uri.path.substring(prefix.length + 1); |
1394 | 1414 |
1395 server.addHandler(reportPath, (HttpRequest request) { | 1415 server.addHandler(reportPath, (HttpRequest request) { |
1396 noCache(request); | 1416 noCache(request); |
1397 handleReport(request, browserId(request, reportPath), testId(request), | 1417 handleReport(request, browserId(request, reportPath), testId(request), |
1398 isStatusUpdate: false); | 1418 isStatusUpdate: false); |
1399 }); | 1419 }); |
1400 server.addHandler(statusUpdatePath, (HttpRequest request) { | 1420 server.addHandler(statusUpdatePath, (HttpRequest request) { |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1851 </div> | 1871 </div> |
1852 <div id="embedded_iframe_div" class="test box"> | 1872 <div id="embedded_iframe_div" class="test box"> |
1853 <iframe id="embedded_iframe"></iframe> | 1873 <iframe id="embedded_iframe"></iframe> |
1854 </div> | 1874 </div> |
1855 </body> | 1875 </body> |
1856 </html> | 1876 </html> |
1857 """; | 1877 """; |
1858 return driverContent; | 1878 return driverContent; |
1859 } | 1879 } |
1860 } | 1880 } |
OLD | NEW |