blob: a31a3261ff0c3f66fdb24a540bb3406aa7cb7d92 [file] [log] [blame]
// 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';
import 'package:meta/meta.dart';
import 'application_package.dart';
import 'base/file_system.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'commands/trace.dart';
import 'device.dart';
import 'globals.dart';
import 'resident_runner.dart';
class ColdRunner extends ResidentRunner {
ColdRunner(
Device device, {
String target,
DebuggingOptions debuggingOptions,
bool usesTerminalUI: true,
this.traceStartup: false,
this.applicationBinary,
bool stayResident: true,
}) : super(device,
target: target,
debuggingOptions: debuggingOptions,
usesTerminalUI: usesTerminalUI,
stayResident: stayResident);
LaunchResult _result;
final bool traceStartup;
final String applicationBinary;
bool get prebuiltMode => applicationBinary != null;
@override
Future<int> run({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<Null> appStartedCompleter,
String route,
bool shouldBuild: true
}) async {
if (!prebuiltMode) {
if (!fs.isFileSync(mainPath)) {
String message = 'Tried to run $mainPath, but that file does not exist.';
if (target == null)
message += '\nConsider using the -t option to specify the Dart file to start.';
printError(message);
return 1;
}
}
package = getApplicationPackageForPlatform(device.targetPlatform, applicationBinary: applicationBinary);
if (package == null) {
String message = 'No application found for ${device.targetPlatform}.';
final String hint = getMissingPackageHintForPlatform(device.targetPlatform);
if (hint != null)
message += '\n$hint';
printError(message);
return 1;
}
final Stopwatch startTime = new Stopwatch()..start();
Map<String, dynamic> platformArgs;
if (traceStartup != null)
platformArgs = <String, dynamic>{ 'trace-startup': traceStartup };
await startEchoingDeviceLog(package);
final String modeName = getModeName(debuggingOptions.buildMode);
if (mainPath == null) {
assert(prebuiltMode);
printStatus('Launching ${package.displayName} on ${device.name} in $modeName mode...');
} else {
printStatus('Launching ${getDisplayPath(mainPath)} on ${device.name} in $modeName mode...');
}
_result = await device.startApp(
package,
debuggingOptions.buildMode,
mainPath: mainPath,
debuggingOptions: debuggingOptions,
platformArgs: platformArgs,
route: route,
prebuiltApplication: prebuiltMode,
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies()
);
if (!_result.started) {
printError('Error running application on ${device.name}.');
await stopEchoingDeviceLog();
return 2;
}
startTime.stop();
// Connect to observatory.
if (debuggingOptions.debuggingEnabled)
await connectToServiceProtocol(_result.observatoryUri);
if (_result.hasObservatory) {
connectionInfoCompleter?.complete(new DebugConnectionInfo(
httpUri: _result.observatoryUri,
wsUri: vmService.wsAddress,
));
}
printTrace('Application running.');
if (vmService != null) {
device.getLogReader(app: package).appPid = vmService.vm.pid;
await vmService.vm.refreshViews();
printTrace('Connected to ${vmService.vm.firstView}\.');
}
if (vmService != null && traceStartup) {
printStatus('Downloading startup trace info...');
try {
await downloadStartupTrace(vmService);
} catch(error) {
printError(error);
return 2;
}
appFinished();
} else if (stayResident) {
setupTerminal();
registerSignalHandlers();
}
appStartedCompleter?.complete();
if (stayResident)
return waitForAppToFinish();
await cleanupAtFinish();
return 0;
}
@override
Future<Null> handleTerminalCommand(String code) async => null;
@override
Future<Null> cleanupAfterSignal() async {
await stopEchoingDeviceLog();
await stopApp();
}
@override
Future<Null> cleanupAtFinish() async {
await stopEchoingDeviceLog();
}
@override
void printHelp({ @required bool details }) {
bool haveDetails = false;
if (_result.hasObservatory)
printStatus('The Observatory debugger and profiler is available at: ${_result.observatoryUri}');
if (supportsServiceProtocol) {
haveDetails = true;
if (details)
printHelpDetails();
}
if (haveDetails && !details) {
printStatus('For a more detailed help message, press "h". To quit, press "q".');
} else {
printStatus('To repeat this help message, press "h". To quit, press "q".');
}
}
@override
Future<Null> preStop() async {
// If we're running in release mode, stop the app using the device logic.
if (vmService == null)
await device.stopApp(package);
}
}