1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/// Convenience methods for Flutter application driving on Fuchsia. Can 6/// be run on either a host machine (making a remote connection to a Fuchsia 7/// device), or on the target Fuchsia machine. 8import 'dart:async'; 9import 'dart:core'; 10import 'dart:io'; 11 12import 'package:fuchsia_remote_debug_protocol/fuchsia_remote_debug_protocol.dart'; 13 14import 'error.dart'; 15 16class _DummyPortForwarder implements PortForwarder { 17 _DummyPortForwarder(this._port, this._remotePort); 18 19 final int _port; 20 final int _remotePort; 21 22 @override 23 int get port => _port; 24 25 @override 26 int get remotePort => _remotePort; 27 28 @override 29 Future<void> stop() async { } 30} 31 32class _DummySshCommandRunner implements SshCommandRunner { 33 _DummySshCommandRunner(); 34 35 final Logger _log = Logger('_DummySshCommandRunner'); 36 37 @override 38 String get sshConfigPath => null; 39 40 @override 41 String get address => InternetAddress.loopbackIPv4.address; 42 43 @override 44 String get interface => null; 45 46 @override 47 Future<List<String>> run(String command) async { 48 try { 49 final List<String> splitCommand = command.split(' '); 50 final String exe = splitCommand[0]; 51 final List<String> args = splitCommand.skip(1).toList(); 52 // This needs to remain async in the event that this command attempts to 53 // access something (like the hub) that requires interaction with this 54 // process's event loop. A specific example is attempting to run `find`, a 55 // synchronous command, on this own process's `out` directory. As `find` 56 // will wait indefinitely for the `out` directory to be serviced, causing 57 // a deadlock. 58 final ProcessResult r = await Process.run(exe, args); 59 return r.stdout.split('\n'); 60 } on ProcessException catch (e) { 61 _log.warning("Error running '$command': $e"); 62 } 63 return <String>[]; 64 } 65} 66 67Future<PortForwarder> _dummyPortForwardingFunction( 68 String address, 69 int remotePort, [ 70 String interface = '', 71 String configFile, 72]) async { 73 return _DummyPortForwarder(remotePort, remotePort); 74} 75 76/// Utility class for creating connections to the Fuchsia Device. 77/// 78/// If executed on a host (non-Fuchsia device), behaves the same as running 79/// [FuchsiaRemoteConnection.connect] whereby the `FUCHSIA_REMOTE_URL` and 80/// `FUCHSIA_SSH_CONFIG` variables must be set. If run on a Fuchsia device, will 81/// connect locally without need for environment variables. 82class FuchsiaCompat { 83 static void _init() { 84 fuchsiaPortForwardingFunction = _dummyPortForwardingFunction; 85 } 86 87 /// Restores state to normal if running on a Fuchsia device. 88 /// 89 /// Noop if running on the host machine. 90 static void cleanup() { 91 restoreFuchsiaPortForwardingFunction(); 92 } 93 94 /// Creates a connection to the Fuchsia device's Dart VM's. 95 /// 96 /// See [FuchsiaRemoteConnection.connect] for more details. 97 /// [FuchsiaCompat.cleanup] must be called when the connection is no longer in 98 /// use. It is the caller's responsibility to call 99 /// [FuchsiaRemoteConnection.stop]. 100 static Future<FuchsiaRemoteConnection> connect() async { 101 FuchsiaCompat._init(); 102 return FuchsiaRemoteConnection.connectWithSshCommandRunner( 103 _DummySshCommandRunner()); 104 } 105} 106