run_cold.dart 4.62 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
// TODO(flutter/flutter#23031): Test this.
16 17
class ColdRunner extends ResidentRunner {
  ColdRunner(
18
    List<FlutterDevice> devices, {
19 20
    String target,
    DebuggingOptions debuggingOptions,
21 22
    bool usesTerminalUI = true,
    this.traceStartup = false,
23
    this.applicationBinary,
24 25
    bool stayResident = true,
    bool ipv6 = false,
26
  }) : super(devices,
27 28
             target: target,
             debuggingOptions: debuggingOptions,
29
             usesTerminalUI: usesTerminalUI,
30 31
             stayResident: stayResident,
             ipv6: ipv6);
32

33
  final bool traceStartup;
34
  final File applicationBinary;
35

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

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

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

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

76
    printTrace('Application running.');
77

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

86 87 88 89 90 91 92 93
    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) {
94
          printError('Error downloading startup trace: $error');
95 96
          return 2;
        }
97
      }
98
      appFinished();
99
    } else if (stayResident) {
100 101
      setupTerminal();
      registerSignalHandlers();
102 103
    }

104 105
    appStartedCompleter?.complete();

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

112
  @override
113
  Future<void> handleTerminalCommand(String code) async { }
114

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

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

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

  @override
156
  Future<void> preStop() async {
157 158 159 160 161
    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);
    }
162
  }
163
}