| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file | 
|  | 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. | 
|  | 4 | 
|  | 5 library test.runner.browser.safari; | 
|  | 6 | 
|  | 7 import 'dart:async'; | 
|  | 8 import 'dart:convert'; | 
|  | 9 import 'dart:io'; | 
|  | 10 | 
|  | 11 import 'package:path/path.dart' as p; | 
|  | 12 | 
|  | 13 import '../../util/io.dart'; | 
|  | 14 import 'browser.dart'; | 
|  | 15 | 
|  | 16 /// A class for running an instance of Safari. | 
|  | 17 /// | 
|  | 18 /// Any errors starting or running the process are reported through [onExit]. | 
|  | 19 class Safari implements Browser { | 
|  | 20   /// The underlying process. | 
|  | 21   Process _process; | 
|  | 22 | 
|  | 23   Future get onExit => _onExitCompleter.future; | 
|  | 24   final _onExitCompleter = new Completer(); | 
|  | 25 | 
|  | 26   /// A future that completes when the browser process has started. | 
|  | 27   /// | 
|  | 28   /// This is used to ensure that [close] works regardless of when it's called. | 
|  | 29   Future get _onProcessStarted => _onProcessStartedCompleter.future; | 
|  | 30   final _onProcessStartedCompleter = new Completer(); | 
|  | 31 | 
|  | 32   /// Starts a new instance of Safari open to the given [url], which may be a | 
|  | 33   /// [Uri] or a [String]. | 
|  | 34   /// | 
|  | 35   /// If [executable] is passed, it's used as the Safari executable. Otherwise | 
|  | 36   /// the default executable name for the current OS will be used. | 
|  | 37   Safari(url, {String executable}) { | 
|  | 38     if (executable == null) { | 
|  | 39       executable = '/Applications/Safari.app/Contents/MacOS/Safari'; | 
|  | 40     } | 
|  | 41 | 
|  | 42     // Don't return a Future here because there's no need for the caller to wait | 
|  | 43     // for the process to actually start. They should just wait for the HTTP | 
|  | 44     // request instead. | 
|  | 45     withTempDir((dir) { | 
|  | 46       // Safari will only open files (not general URLs) via the command-line | 
|  | 47       // API, so we create a dummy file to redirect it to the page we actually | 
|  | 48       // want it to load. | 
|  | 49       var redirect = p.join(dir, 'redirect.html'); | 
|  | 50       new File(redirect).writeAsStringSync( | 
|  | 51           "<script>location = " + JSON.encode(url.toString()) + "</script>"); | 
|  | 52 | 
|  | 53       return Process.start(executable, [redirect]).then((process) { | 
|  | 54         _process = process; | 
|  | 55         _onProcessStartedCompleter.complete(); | 
|  | 56 | 
|  | 57         // TODO(nweiz): the browser's standard output is almost always useless | 
|  | 58         // noise, but we should allow the user to opt in to seeing it. | 
|  | 59         return _process.exitCode; | 
|  | 60       }); | 
|  | 61     }).then((exitCode) { | 
|  | 62       if (exitCode != 0) throw "Safari failed with exit code $exitCode."; | 
|  | 63     }).then(_onExitCompleter.complete) | 
|  | 64         .catchError(_onExitCompleter.completeError); | 
|  | 65   } | 
|  | 66 | 
|  | 67   Future close() { | 
|  | 68     _onProcessStarted.then((_) => _process.kill()); | 
|  | 69 | 
|  | 70     // Swallow exceptions. The user should explicitly use [onExit] for these. | 
|  | 71     return onExit.catchError((_) {}); | 
|  | 72   } | 
|  | 73 } | 
| OLD | NEW | 
|---|