[flutter_tools] remove globals from desktop configuration (#67146)

Refactors the desktop devices and workflow to remove unnecessary usage of global variables. This should make it easier to test and continue enhancing the desktop functionality of the tooling

#47161
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index a2579f5..9280f4b 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -615,14 +615,13 @@
     ProtocolDiscovery observatoryDiscovery;
 
     if (debuggingOptions.debuggingEnabled) {
-      // TODO(devoncarew): Remember the forwarding information (so we can later remove the
-      // port forwarding or set it up again when adb fails on us).
       observatoryDiscovery = ProtocolDiscovery.observatory(
         await getLogReader(),
         portForwarder: portForwarder,
         hostPort: debuggingOptions.hostVmServicePort,
         devicePort: debuggingOptions.deviceVmServicePort,
         ipv6: ipv6,
+        logger: _logger,
       );
     }
 
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 00a85df..6089ce8 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -144,10 +144,12 @@
         config: globals.config,
         fuchsiaWorkflow: fuchsiaWorkflow,
         xcDevice: globals.xcdevice,
+        windowsWorkflow: windowsWorkflow,
         macOSWorkflow: MacOSWorkflow(
           platform: globals.platform,
           featureFlags: featureFlags,
         ),
+        operatingSystemUtils: globals.os,
       ),
       Doctor: () => Doctor(logger: globals.logger),
       DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
@@ -249,7 +251,10 @@
         featureFlags: featureFlags,
         platform: globals.platform,
       ),
-      WindowsWorkflow: () => const WindowsWorkflow(),
+      WindowsWorkflow: () => WindowsWorkflow(
+        featureFlags: featureFlags,
+        platform: globals.platform,
+      ),
       Xcode: () => Xcode(
         logger: globals.logger,
         processManager: globals.processManager,
diff --git a/packages/flutter_tools/lib/src/desktop_device.dart b/packages/flutter_tools/lib/src/desktop_device.dart
index 3f6340f..3fa0d1b 100644
--- a/packages/flutter_tools/lib/src/desktop_device.dart
+++ b/packages/flutter_tools/lib/src/desktop_device.dart
@@ -12,11 +12,11 @@
 import 'base/file_system.dart';
 import 'base/io.dart';
 import 'base/logger.dart';
+import 'base/os.dart';
 import 'build_info.dart';
 import 'convert.dart';
 import 'devfs.dart';
 import 'device.dart';
-import 'globals.dart' as globals;
 import 'protocol_discovery.dart';
 
 /// A partial implementation of Device for desktop-class devices to inherit
@@ -25,12 +25,14 @@
   DesktopDevice(String identifier, {
       @required PlatformType platformType,
       @required bool ephemeral,
-      Logger logger,
-      ProcessManager processManager,
-      FileSystem fileSystem,
-    }) : _logger = logger ?? globals.logger, // TODO(jonahwilliams): remove after updating google3
-         _processManager = processManager ?? globals.processManager,
-         _fileSystem = fileSystem ?? globals.fs,
+      @required Logger logger,
+      @required ProcessManager processManager,
+      @required FileSystem fileSystem,
+      @required OperatingSystemUtils operatingSystemUtils,
+    }) : _logger = logger,
+         _processManager = processManager,
+         _fileSystem = fileSystem,
+         _operatingSystemUtils = operatingSystemUtils,
          super(
           identifier,
           category: Category.desktop,
@@ -41,6 +43,7 @@
   final Logger _logger;
   final ProcessManager _processManager;
   final FileSystem _fileSystem;
+  final OperatingSystemUtils _operatingSystemUtils;
   final Set<Process> _runningProcesses = <Process>{};
   final DesktopLogReader _deviceLogReader = DesktopLogReader();
 
@@ -86,7 +89,7 @@
   DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();
 
   @override
-  Future<String> get sdkNameAndVersion async => globals.os.name;
+  Future<String> get sdkNameAndVersion async => _operatingSystemUtils.name;
 
   @override
   bool supportsRuntimeMode(BuildMode buildMode) => buildMode != BuildMode.jitRelease;
@@ -130,9 +133,11 @@
       return LaunchResult.failed();
     }
 
-    final Process process = await _processManager.start(<String>[
-      executable,
-    ]);
+    final Process process = await _processManager.start(
+      <String>[
+        executable,
+      ],
+    );
     _runningProcesses.add(process);
     unawaited(process.exitCode.then((_) => _runningProcesses.remove(process)));
 
@@ -144,6 +149,7 @@
       devicePort: debuggingOptions?.deviceVmServicePort,
       hostPort: debuggingOptions?.hostVmServicePort,
       ipv6: ipv6,
+      logger: _logger,
     );
     try {
       final Uri observatoryUri = await observatoryDiscovery.uri;
@@ -172,7 +178,7 @@
     // Walk a copy of _runningProcesses, since the exit handler removes from the
     // set.
     for (final Process process in Set<Process>.of(_runningProcesses)) {
-      succeeded &= process.kill();
+      succeeded &= _processManager.killPid(process.pid);
     }
     return succeeded;
   }
@@ -198,9 +204,12 @@
   void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
 }
 
+/// A log reader for desktop applications that delegates to a [Process] stdout
+/// and stderr streams.
 class DesktopLogReader extends DeviceLogReader {
   final StreamController<List<int>> _inputController = StreamController<List<int>>.broadcast();
 
+  /// Begin listening to the stdout and stderr streams of the provided [process].
   void initializeProcess(Process process) {
     process.stdout.listen(_inputController.add);
     process.stderr.listen(_inputController.add);
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index cdc2c70..614a026 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -21,6 +21,7 @@
 import 'base/file_system.dart';
 import 'base/io.dart';
 import 'base/logger.dart';
+import 'base/os.dart';
 import 'base/platform.dart';
 import 'base/user_messages.dart';
 import 'base/utils.dart';
@@ -42,6 +43,7 @@
 import 'version.dart';
 import 'web/web_device.dart';
 import 'windows/windows_device.dart';
+import 'windows/windows_workflow.dart';
 
 DeviceManager get deviceManager => context.get<DeviceManager>();
 
@@ -340,6 +342,8 @@
     @required Config config,
     @required Artifacts artifacts,
     @required MacOSWorkflow macOSWorkflow,
+    @required OperatingSystemUtils operatingSystemUtils,
+    @required WindowsWorkflow windowsWorkflow,
   }) : deviceDiscoverers =  <DeviceDiscovery>[
     AndroidDevices(
       logger: logger,
@@ -376,6 +380,7 @@
       logger: logger,
       platform: platform,
       fileSystem: fileSystem,
+      operatingSystemUtils: operatingSystemUtils,
     ),
     LinuxDevices(
       platform: platform,
@@ -383,8 +388,15 @@
       processManager: processManager,
       logger: logger,
       fileSystem: fileSystem,
+      operatingSystemUtils: operatingSystemUtils,
     ),
-    WindowsDevices(),
+    WindowsDevices(
+      processManager: processManager,
+      operatingSystemUtils: operatingSystemUtils,
+      logger: logger,
+      fileSystem: fileSystem,
+      windowsWorkflow: windowsWorkflow,
+    ),
     WebDevices(
       featureFlags: featureFlags,
       fileSystem: fileSystem,
diff --git a/packages/flutter_tools/lib/src/linux/linux_device.dart b/packages/flutter_tools/lib/src/linux/linux_device.dart
index 47f0621..a860d16 100644
--- a/packages/flutter_tools/lib/src/linux/linux_device.dart
+++ b/packages/flutter_tools/lib/src/linux/linux_device.dart
@@ -7,12 +7,12 @@
 
 import '../base/file_system.dart';
 import '../base/logger.dart';
+import '../base/os.dart';
 import '../base/platform.dart';
 import '../build_info.dart';
 import '../desktop_device.dart';
 import '../device.dart';
 import '../features.dart';
-import '../globals.dart' as globals;
 import '../project.dart';
 import 'application_package.dart';
 import 'build_linux.dart';
@@ -24,6 +24,7 @@
     @required ProcessManager processManager,
     @required Logger logger,
     @required FileSystem fileSystem,
+    @required OperatingSystemUtils operatingSystemUtils,
   }) : super(
       'linux',
       platformType: PlatformType.linux,
@@ -31,6 +32,7 @@
       logger: logger,
       processManager: processManager,
       fileSystem: fileSystem,
+      operatingSystemUtils: operatingSystemUtils,
   );
 
   @override
@@ -70,17 +72,19 @@
   LinuxDevices({
     @required Platform platform,
     @required FeatureFlags featureFlags,
-    FileSystem fileSystem,
-    ProcessManager processManager,
-    Logger logger,
-  }) : _platform = platform ?? globals.platform, // TODO(jonahwilliams): remove after google3 roll
+    @required OperatingSystemUtils operatingSystemUtils,
+    @required FileSystem fileSystem,
+    @required ProcessManager processManager,
+    @required Logger logger,
+  }) : _platform = platform,
        _linuxWorkflow = LinuxWorkflow(
           platform: platform,
           featureFlags: featureFlags,
        ),
-       _fileSystem = fileSystem ?? globals.fs,
+       _fileSystem = fileSystem,
        _logger = logger,
-       _processManager = processManager ?? globals.processManager,
+       _processManager = processManager,
+       _operatingSystemUtils = operatingSystemUtils,
        super('linux devices');
 
   final Platform _platform;
@@ -88,6 +92,7 @@
   final ProcessManager _processManager;
   final Logger _logger;
   final FileSystem _fileSystem;
+  final OperatingSystemUtils _operatingSystemUtils;
 
   @override
   bool get supportsPlatform => _platform.isLinux;
@@ -105,6 +110,7 @@
         logger: _logger,
         processManager: _processManager,
         fileSystem: _fileSystem,
+        operatingSystemUtils: _operatingSystemUtils,
       ),
     ];
   }
diff --git a/packages/flutter_tools/lib/src/macos/macos_device.dart b/packages/flutter_tools/lib/src/macos/macos_device.dart
index 17c7fb0..934011f 100644
--- a/packages/flutter_tools/lib/src/macos/macos_device.dart
+++ b/packages/flutter_tools/lib/src/macos/macos_device.dart
@@ -8,11 +8,11 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/logger.dart';
+import '../base/os.dart';
 import '../base/platform.dart';
 import '../build_info.dart';
 import '../desktop_device.dart';
 import '../device.dart';
-import '../globals.dart' as globals;
 import '../macos/application_package.dart';
 import '../project.dart';
 import 'build_macos.dart';
@@ -23,7 +23,8 @@
   MacOSDevice({
     @required ProcessManager processManager,
     @required Logger logger,
-    FileSystem fileSystem,
+    @required FileSystem fileSystem,
+    @required OperatingSystemUtils operatingSystemUtils,
   }) : _processManager = processManager,
        _logger = logger,
        super(
@@ -32,7 +33,8 @@
         ephemeral: false,
         processManager: processManager,
         logger: logger,
-        fileSystem: fileSystem ?? globals.fs,
+        fileSystem: fileSystem,
+        operatingSystemUtils: operatingSystemUtils,
       );
 
   final ProcessManager _processManager;
@@ -93,12 +95,14 @@
     @required MacOSWorkflow macOSWorkflow,
     @required ProcessManager processManager,
     @required Logger logger,
-    FileSystem fileSystem,
+    @required FileSystem fileSystem,
+    @required OperatingSystemUtils operatingSystemUtils,
   }) : _logger = logger,
        _platform = platform,
        _macOSWorkflow = macOSWorkflow,
        _processManager = processManager,
-       _fileSystem = fileSystem ?? globals.fs,
+       _fileSystem = fileSystem,
+       _operatingSystemUtils = operatingSystemUtils,
        super('macOS devices');
 
   final MacOSWorkflow _macOSWorkflow;
@@ -106,6 +110,7 @@
   final ProcessManager _processManager;
   final Logger _logger;
   final FileSystem _fileSystem;
+  final OperatingSystemUtils _operatingSystemUtils;
 
   @override
   bool get supportsPlatform => _platform.isMacOS;
@@ -123,6 +128,7 @@
         processManager: _processManager,
         logger: _logger,
         fileSystem: _fileSystem,
+        operatingSystemUtils: _operatingSystemUtils,
       ),
     ];
   }
diff --git a/packages/flutter_tools/lib/src/protocol_discovery.dart b/packages/flutter_tools/lib/src/protocol_discovery.dart
index bdcbb45..96d238a 100644
--- a/packages/flutter_tools/lib/src/protocol_discovery.dart
+++ b/packages/flutter_tools/lib/src/protocol_discovery.dart
@@ -7,6 +7,7 @@
 import 'package:meta/meta.dart';
 
 import 'base/io.dart';
+import 'base/logger.dart';
 import 'device.dart';
 import 'globals.dart' as globals;
 
@@ -22,8 +23,9 @@
     this.hostPort,
     this.devicePort,
     this.ipv6,
-  }) : assert(logReader != null)
-  {
+    Logger logger,
+  }) : _logger = logger,
+       assert(logReader != null) {
     _deviceLogSubscription = logReader.logLines.listen(
       _handleLine,
       onDone: _stopScrapingLogs,
@@ -39,6 +41,7 @@
     @required int hostPort,
     @required int devicePort,
     @required bool ipv6,
+    Logger logger, // TODO(jonahwilliams): make required.
   }) {
     const String kObservatoryService = 'Observatory';
     return ProtocolDiscovery._(
@@ -50,6 +53,7 @@
       hostPort: hostPort,
       devicePort: devicePort,
       ipv6: ipv6,
+      logger: logger ?? globals.logger,
     );
   }
 
@@ -59,6 +63,7 @@
   final int hostPort;
   final int devicePort;
   final bool ipv6;
+  final Logger _logger;
 
   /// The time to wait before forwarding a new observatory URIs from [logReader].
   final Duration throttleDuration;
@@ -138,20 +143,20 @@
       return;
     }
     if (devicePort != null && uri.port != devicePort) {
-      globals.printTrace('skipping potential observatory $uri due to device port mismatch');
+      _logger.printTrace('skipping potential observatory $uri due to device port mismatch');
       return;
     }
     _uriStreamController.add(uri);
   }
 
   Future<Uri> _forwardPort(Uri deviceUri) async {
-    globals.printTrace('$serviceName URL on device: $deviceUri');
+    _logger.printTrace('$serviceName URL on device: $deviceUri');
     Uri hostUri = deviceUri;
 
     if (portForwarder != null) {
       final int actualDevicePort = deviceUri.port;
       final int actualHostPort = await portForwarder.forward(actualDevicePort, hostPort: hostPort);
-      globals.printTrace('Forwarded host port $actualHostPort to device port $actualDevicePort for $serviceName');
+      _logger.printTrace('Forwarded host port $actualHostPort to device port $actualDevicePort for $serviceName');
       hostUri = deviceUri.replace(port: actualHostPort);
     }
 
diff --git a/packages/flutter_tools/lib/src/windows/windows_device.dart b/packages/flutter_tools/lib/src/windows/windows_device.dart
index 91550a6..70233f0 100644
--- a/packages/flutter_tools/lib/src/windows/windows_device.dart
+++ b/packages/flutter_tools/lib/src/windows/windows_device.dart
@@ -3,13 +3,16 @@
 // found in the LICENSE file.
 
 import 'package:meta/meta.dart';
+import 'package:process/process.dart';
 
+import '../base/file_system.dart';
 import '../base/io.dart';
+import '../base/logger.dart';
+import '../base/os.dart';
 import '../base/process.dart';
 import '../build_info.dart';
 import '../desktop_device.dart';
 import '../device.dart';
-import '../globals.dart' as globals;
 import '../project.dart';
 import 'application_package.dart';
 import 'build_windows.dart';
@@ -17,10 +20,19 @@
 
 /// A device that represents a desktop Windows target.
 class WindowsDevice extends DesktopDevice {
-  WindowsDevice() : super(
+  WindowsDevice({
+    @required ProcessManager processManager,
+    @required Logger logger,
+    @required FileSystem fileSystem,
+    @required OperatingSystemUtils operatingSystemUtils,
+  }) : super(
       'windows',
       platformType: PlatformType.windows,
       ephemeral: false,
+      processManager: processManager,
+      logger: logger,
+      fileSystem: fileSystem,
+      operatingSystemUtils: operatingSystemUtils,
   );
 
   @override
@@ -57,13 +69,30 @@
 }
 
 class WindowsDevices extends PollingDeviceDiscovery {
-  WindowsDevices() : super('windows devices');
+  WindowsDevices({
+    @required ProcessManager processManager,
+    @required Logger logger,
+    @required FileSystem fileSystem,
+    @required OperatingSystemUtils operatingSystemUtils,
+    @required WindowsWorkflow windowsWorkflow,
+  }) : _fileSystem = fileSystem,
+      _logger = logger,
+      _processManager = processManager,
+      _operatingSystemUtils = operatingSystemUtils,
+      _windowsWorkflow = windowsWorkflow,
+      super('windows devices');
+
+  final FileSystem _fileSystem;
+  final Logger _logger;
+  final ProcessManager _processManager;
+  final OperatingSystemUtils _operatingSystemUtils;
+  final WindowsWorkflow _windowsWorkflow;
 
   @override
-  bool get supportsPlatform => globals.platform.isWindows;
+  bool get supportsPlatform => _windowsWorkflow.appliesToHostPlatform;
 
   @override
-  bool get canListAnything => windowsWorkflow.canListDevices;
+  bool get canListAnything => _windowsWorkflow.canListDevices;
 
   @override
   Future<List<Device>> pollingGetDevices({ Duration timeout }) async {
@@ -71,7 +100,12 @@
       return const <Device>[];
     }
     return <Device>[
-      WindowsDevice(),
+      WindowsDevice(
+        fileSystem: _fileSystem,
+        logger: _logger,
+        processManager: _processManager,
+        operatingSystemUtils: _operatingSystemUtils,
+      ),
     ];
   }
 
diff --git a/packages/flutter_tools/lib/src/windows/windows_workflow.dart b/packages/flutter_tools/lib/src/windows/windows_workflow.dart
index 72dddea..2144f62 100644
--- a/packages/flutter_tools/lib/src/windows/windows_workflow.dart
+++ b/packages/flutter_tools/lib/src/windows/windows_workflow.dart
@@ -2,29 +2,38 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:meta/meta.dart';
+
 import '../base/context.dart';
+import '../base/platform.dart';
 import '../doctor.dart';
 import '../features.dart';
-import '../globals.dart' as globals;
 
 /// The [WindowsWorkflow] instance.
 WindowsWorkflow get windowsWorkflow => context.get<WindowsWorkflow>();
 
-/// The windows-specific implementation of a [Workflow].
+/// The Windows-specific implementation of a [Workflow].
 ///
-/// This workflow requires the flutter-desktop-embedding as a sibling
-/// repository to the flutter repo.
+/// This workflow requires the host machine to be Windows, and the Windows
+/// desktop configuration setting to be enabled.
 class WindowsWorkflow implements Workflow {
-  const WindowsWorkflow();
+  const WindowsWorkflow({
+    @required Platform platform,
+    @required FeatureFlags featureFlags,
+  }) : _platform = platform,
+       _featureFlags = featureFlags;
+
+  final Platform _platform;
+  final FeatureFlags _featureFlags;
 
   @override
-  bool get appliesToHostPlatform => globals.platform.isWindows && featureFlags.isWindowsEnabled;
+  bool get appliesToHostPlatform => _platform.isWindows && _featureFlags.isWindowsEnabled;
 
   @override
-  bool get canLaunchDevices => globals.platform.isWindows && featureFlags.isWindowsEnabled;
+  bool get canLaunchDevices => _platform.isWindows && _featureFlags.isWindowsEnabled;
 
   @override
-  bool get canListDevices => globals.platform.isWindows && featureFlags.isWindowsEnabled;
+  bool get canListDevices => _platform.isWindows && _featureFlags.isWindowsEnabled;
 
   @override
   bool get canListEmulators => false;