run_cold.dart 4.58 KB
Newer Older
1 2 3 4 5 6
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

7
import 'package:meta/meta.dart';
8

9
import 'base/file_system.dart';
10 11
import 'device.dart';
import 'globals.dart';
12
import 'resident_runner.dart';
13
import 'tracing.dart';
14

15 16
class ColdRunner extends ResidentRunner {
  ColdRunner(
17
    List<FlutterDevice> devices, {
18 19
    String target,
    DebuggingOptions debuggingOptions,
20 21
    bool usesTerminalUI = true,
    this.traceStartup = false,
22
    this.applicationBinary,
23 24
    bool stayResident = true,
    bool ipv6 = false,
25
  }) : super(devices,
26 27
             target: target,
             debuggingOptions: debuggingOptions,
28
             usesTerminalUI: usesTerminalUI,
29 30
             stayResident: stayResident,
             ipv6: ipv6);
31

32
  final bool traceStartup;
33
  final File applicationBinary;
34

35
  @override
36
  Future<int> run({
37
    Completer<DebugConnectionInfo> connectionInfoCompleter,
38
    Completer<void> appStartedCompleter,
39
    String route,
40
    bool shouldBuild = true
41
  }) async {
42
    final bool prebuiltMode = applicationBinary != null;
43
    if (!prebuiltMode) {
44 45
      if (!fs.isFileSync(mainPath)) {
        String message = 'Tried to run $mainPath, but that file does not exist.';
46 47 48 49 50
        if (target == null)
          message += '\nConsider using the -t option to specify the Dart file to start.';
        printError(message);
        return 1;
      }
51 52
    }

53 54 55 56 57 58 59 60
    for (FlutterDevice device in flutterDevices) {
      final int result = await device.runCold(
        coldRunner: this,
        route: route,
        shouldBuild: shouldBuild,
      );
      if (result != 0)
        return result;
61 62
    }

63
    // Connect to observatory.
64
    if (debuggingOptions.debuggingEnabled)
65
      await connectToServiceProtocol();
66

67 68
    if (flutterDevices.first.observatoryUris != null) {
      // For now, only support one debugger connection.
69
      connectionInfoCompleter?.complete(DebugConnectionInfo(
70 71
        httpUri: flutterDevices.first.observatoryUris.first,
        wsUri: flutterDevices.first.vmServices.first.wsAddress,
72 73
      ));
    }
74

75
    printTrace('Application running.');
76

77 78 79 80 81 82
    for (FlutterDevice device in flutterDevices) {
      if (device.vmServices == null)
        continue;
      device.initLogReader();
      await device.refreshViews();
      printTrace('Connected to ${device.device.name}');
83
    }
84

85 86 87 88 89 90 91 92
    if (traceStartup) {
      // Only trace startup for the first device.
      final FlutterDevice device = flutterDevices.first;
      if (device.vmServices != null && device.vmServices.isNotEmpty) {
        printStatus('Downloading startup trace info for ${device.device.name}');
        try {
          await downloadStartupTrace(device.vmServices.first);
        } catch (error) {
93
          printError('Error downloading startup trace: $error');
94 95
          return 2;
        }
96
      }
97
      appFinished();
98
    } else if (stayResident) {
99 100
      setupTerminal();
      registerSignalHandlers();
101 102
    }

103 104
    appStartedCompleter?.complete();

105 106 107 108
    if (stayResident)
      return waitForAppToFinish();
    await cleanupAtFinish();
    return 0;
109 110
  }

111
  @override
112
  Future<Null> handleTerminalCommand(String code) async => null;
113

114 115 116 117
  @override
  Future<Null> cleanupAfterSignal() async {
    await stopEchoingDeviceLog();
    await stopApp();
118 119
  }

120 121 122
  @override
  Future<Null> cleanupAtFinish() async {
    await stopEchoingDeviceLog();
123 124
  }

125
  @override
126
  void printHelp({ @required bool details }) {
127
    bool haveDetails = false;
128
    bool haveAnything = false;
129 130 131
    for (FlutterDevice device in flutterDevices) {
      final String dname = device.device.name;
      if (device.observatoryUris != null) {
132
        for (Uri uri in device.observatoryUris) {
133
          printStatus('An Observatory debugger and profiler on $dname is available at $uri');
134 135
          haveAnything = true;
        }
136 137
      }
    }
138 139
    if (supportsServiceProtocol) {
      haveDetails = true;
140
      if (details) {
141
        printHelpDetails();
142 143
        haveAnything = true;
      }
144 145
    }
    if (haveDetails && !details) {
146
      printStatus('For a more detailed help message, press "h". To quit, press "q".');
147
    } else if (haveAnything) {
148
      printStatus('To repeat this help message, press "h". To quit, press "q".');
149 150
    } else {
      printStatus('To quit, press "q".');
151
    }
152
  }
153 154 155

  @override
  Future<Null> preStop() async {
156 157 158 159 160
    for (FlutterDevice device in flutterDevices) {
      // If we're running in release mode, stop the app using the device logic.
      if (device.vmServices == null || device.vmServices.isEmpty)
        await device.device.stopApp(device.package);
    }
161
  }
162
}