// Copyright 2014 The Flutter 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:io' as io;

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:meta/meta.dart' show visibleForTesting;
import 'package:platform/platform.dart';
import 'package:process/process.dart';

import './globals.dart';
import './repository.dart';
import './stdio.dart';

const List<String> expectedEntitlements = <String>[
  'com.apple.security.cs.allow-jit',
  'com.apple.security.cs.allow-unsigned-executable-memory',
  'com.apple.security.cs.allow-dyld-environment-variables',
  'com.apple.security.network.client',
  'com.apple.security.network.server',
  'com.apple.security.cs.disable-library-validation',
];

const String kVerify = 'verify';
const String kSignatures = 'signatures';
const String kRevision = 'revision';
const String kUpstream = 'upstream';


/// Command to codesign and verify the signatures of cached binaries.
class CodesignCommand extends Command<void> {
  CodesignCommand({
    required this.checkouts,
    required this.flutterRoot,
    FrameworkRepository? framework,
  })  : fileSystem = checkouts.fileSystem,
        platform = checkouts.platform,
        stdio = checkouts.stdio,
        processManager = checkouts.processManager {
    if (framework != null) {
      _framework = framework;
    }
    argParser.addFlag(
      kVerify,
      help: 'Only verify expected binaries exist and are codesigned with entitlements.',
    );
    argParser.addFlag(
      kSignatures,
      defaultsTo: true,
      help: 'When off, this command will only verify the existence of binaries, and not their\n'
            'signatures or entitlements. Must be used with --verify flag.',
    );
    argParser.addOption(
      kUpstream,
      defaultsTo: FrameworkRepository.defaultUpstream,
      help: "The git remote URL to use as the Flutter framework's upstream.",
    );
    argParser.addOption(
      kRevision,
      help: 'The Flutter framework revision to use.',
    );
  }

  final Checkouts checkouts;
  final FileSystem fileSystem;
  final Platform platform;
  final ProcessManager processManager;
  final Stdio stdio;

  /// Root directory of the Flutter repository.
  final Directory flutterRoot;

  FrameworkRepository? _framework;
  FrameworkRepository get framework {
    return _framework ??= FrameworkRepository(
      checkouts,
      upstreamRemote: Remote(
        name: RemoteName.upstream,
        url: argResults![kUpstream] as String,
      ),
    );
  }

  @override
  String get name => 'codesign';

  @override
  String get description =>
      'For codesigning and verifying the signatures of engine binaries.';

  @override
  Future<void> run() async {
    if (!platform.isMacOS) {
      throw ConductorException(
        'Error! Expected operating system "macos", actual operating system is: '
        '"${platform.operatingSystem}"',
      );
    }

    if (argResults!['verify'] as bool != true) {
      throw ConductorException(
        'Sorry, but codesigning is not implemented yet. Please pass the '
        '--$kVerify flag to verify signatures.',
      );
    }

    String revision;
    if (argResults!.wasParsed(kRevision)) {
      stdio.printWarning(
        'Warning! When providing an arbitrary revision, the contents of the cache may not '
        'match the expected binaries in the conductor tool. It is preferred to check out '
        'the desired revision and run that version of the conductor.\n',
      );
      revision = argResults![kRevision] as String;
    } else {
      revision = ((await processManager.run(
        <String>['git', 'rev-parse', 'HEAD'],
        workingDirectory: flutterRoot.path,
      )).stdout as String).trim();
      assert(revision.isNotEmpty);
    }

    await framework.checkout(revision);

    // Ensure artifacts present
    await framework.runFlutter(<String>['precache', '--android', '--ios', '--macos']);

    await verifyExist();
    if (argResults![kSignatures] as bool) {
      await verifySignatures();
    }
  }

  /// Binaries that are expected to be codesigned and have entitlements.
  ///
  /// This list should be kept in sync with the actual contents of Flutter's
  /// cache.
  Future<List<String>> get binariesWithEntitlements async {
    final String frameworkCacheDirectory = await framework.cacheDirectory;
    return <String>[
      'artifacts/engine/android-arm-profile/darwin-x64/gen_snapshot',
      'artifacts/engine/android-arm-release/darwin-x64/gen_snapshot',
      'artifacts/engine/android-arm64-profile/darwin-x64/gen_snapshot',
      'artifacts/engine/android-arm64-release/darwin-x64/gen_snapshot',
      'artifacts/engine/android-x64-profile/darwin-x64/gen_snapshot',
      'artifacts/engine/android-x64-release/darwin-x64/gen_snapshot',
      'artifacts/engine/darwin-x64-profile/gen_snapshot',
      'artifacts/engine/darwin-x64-profile/gen_snapshot_arm64',
      'artifacts/engine/darwin-x64-profile/gen_snapshot_x64',
      'artifacts/engine/darwin-x64-release/gen_snapshot',
      'artifacts/engine/darwin-x64-release/gen_snapshot_arm64',
      'artifacts/engine/darwin-x64-release/gen_snapshot_x64',
      'artifacts/engine/darwin-x64/flutter_tester',
      'artifacts/engine/darwin-x64/gen_snapshot',
      'artifacts/engine/darwin-x64/gen_snapshot_arm64',
      'artifacts/engine/darwin-x64/gen_snapshot_x64',
      'artifacts/engine/ios-profile/gen_snapshot_arm64',
      'artifacts/engine/ios-release/gen_snapshot_arm64',
      'artifacts/engine/ios/gen_snapshot_arm64',
      'artifacts/libimobiledevice/idevicescreenshot',
      'artifacts/libimobiledevice/idevicesyslog',
      'artifacts/libimobiledevice/libimobiledevice-1.0.6.dylib',
      'artifacts/libplist/libplist-2.0.3.dylib',
      'artifacts/openssl/libcrypto.1.1.dylib',
      'artifacts/openssl/libssl.1.1.dylib',
      'artifacts/usbmuxd/iproxy',
      'artifacts/usbmuxd/libusbmuxd-2.0.6.dylib',
      'dart-sdk/bin/dart',
      'dart-sdk/bin/dartaotruntime',
      'dart-sdk/bin/utils/gen_snapshot',
      'dart-sdk/bin/utils/wasm-opt',
    ]
        .map((String relativePath) =>
            fileSystem.path.join(frameworkCacheDirectory, relativePath))
        .toList();
  }

  /// Binaries that are only expected to be codesigned.
  ///
  /// This list should be kept in sync with the actual contents of Flutter's
  /// cache.
  Future<List<String>> get binariesWithoutEntitlements async {
    final String frameworkCacheDirectory = await framework.cacheDirectory;
    return <String>[
      'artifacts/engine/darwin-x64-profile/FlutterMacOS.framework/Versions/A/FlutterMacOS',
      'artifacts/engine/darwin-x64-release/FlutterMacOS.framework/Versions/A/FlutterMacOS',
      'artifacts/engine/darwin-x64/FlutterMacOS.framework/Versions/A/FlutterMacOS',
      'artifacts/engine/darwin-x64/font-subset',
      'artifacts/engine/darwin-x64/impellerc',
      'artifacts/engine/darwin-x64/libpath_ops.dylib',
      'artifacts/engine/darwin-x64/libtessellator.dylib',
      'artifacts/engine/ios-profile/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter',
      'artifacts/engine/ios-profile/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/engine/ios-release/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter',
      'artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/engine/ios/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter',
      'artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/ios-deploy/ios-deploy',
    ]
        .map((String relativePath) =>
            fileSystem.path.join(frameworkCacheDirectory, relativePath))
        .toList();
  }

  /// Verify the existence of all expected binaries in cache.
  ///
  /// This function ignores code signatures and entitlements, and is intended to
  /// be run on every commit. It should throw if either new binaries are added
  /// to the cache or expected binaries removed. In either case, this class'
  /// [binariesWithEntitlements] or [binariesWithoutEntitlements] lists should
  /// be updated accordingly.
  @visibleForTesting
  Future<void> verifyExist() async {
    final Set<String> foundFiles = <String>{};
    for (final String binaryPath
        in await findBinaryPaths(await framework.cacheDirectory)) {
      if ((await binariesWithEntitlements).contains(binaryPath)) {
        foundFiles.add(binaryPath);
      } else if ((await binariesWithoutEntitlements).contains(binaryPath)) {
        foundFiles.add(binaryPath);
      } else {
        throw ConductorException(
            'Found unexpected binary in cache: $binaryPath');
      }
    }

    final List<String> allExpectedFiles =
        (await binariesWithEntitlements) + (await binariesWithoutEntitlements);
    if (foundFiles.length < allExpectedFiles.length) {
      final List<String> unfoundFiles = allExpectedFiles
          .where(
            (String file) => !foundFiles.contains(file),
          )
          .toList();
      stdio.printError(
        'Expected binaries not found in cache:\n\n${unfoundFiles.join('\n')}\n\n'
        'If this commit is removing binaries from the cache, this test should be fixed by\n'
        'removing the relevant entry from either the "binariesWithEntitlements" or\n'
        '"binariesWithoutEntitlements" getters in dev/tools/lib/codesign.dart.',
      );
      throw ConductorException('Did not find all expected binaries!');
    }

    stdio.printStatus('All expected binaries present.');
  }

  /// Verify code signatures and entitlements of all binaries in the cache.
  @visibleForTesting
  Future<void> verifySignatures() async {
    final List<String> unsignedBinaries = <String>[];
    final List<String> wrongEntitlementBinaries = <String>[];
    final List<String> unexpectedBinaries = <String>[];
    for (final String binaryPath
        in await findBinaryPaths(await framework.cacheDirectory)) {
      bool verifySignature = false;
      bool verifyEntitlements = false;
      if ((await binariesWithEntitlements).contains(binaryPath)) {
        verifySignature = true;
        verifyEntitlements = true;
      }
      if ((await binariesWithoutEntitlements).contains(binaryPath)) {
        verifySignature = true;
      }
      if (!verifySignature && !verifyEntitlements) {
        unexpectedBinaries.add(binaryPath);
        stdio.printError('Unexpected binary $binaryPath found in cache!');
        continue;
      }
      stdio.printTrace('Verifying the code signature of $binaryPath');
      final io.ProcessResult codeSignResult = await processManager.run(
        <String>[
          'codesign',
          '-vvv',
          binaryPath,
        ],
      );
      if (codeSignResult.exitCode != 0) {
        unsignedBinaries.add(binaryPath);
        stdio.printError(
          'File "$binaryPath" does not appear to be codesigned.\n'
          'The `codesign` command failed with exit code ${codeSignResult.exitCode}:\n'
          '${codeSignResult.stderr}\n',
        );
        continue;
      }
      if (verifyEntitlements) {
        stdio.printTrace('Verifying entitlements of $binaryPath');
        if (!(await hasExpectedEntitlements(binaryPath))) {
          wrongEntitlementBinaries.add(binaryPath);
        }
      }
    }

    // First print all deviations from expectations
    if (unsignedBinaries.isNotEmpty) {
      stdio.printError('Found ${unsignedBinaries.length} unsigned binaries:');
      unsignedBinaries.forEach(stdio.printError);
    }

    if (wrongEntitlementBinaries.isNotEmpty) {
      stdio.printError('Found ${wrongEntitlementBinaries.length} binaries with unexpected entitlements:');
      wrongEntitlementBinaries.forEach(stdio.printError);
    }

    if (unexpectedBinaries.isNotEmpty) {
      stdio.printError('Found ${unexpectedBinaries.length} unexpected binaries in the cache:');
      unexpectedBinaries.forEach(print);
    }

    // Finally, exit on any invalid state
    if (unsignedBinaries.isNotEmpty) {
      throw ConductorException('Test failed because unsigned binaries detected.');
    }

    if (wrongEntitlementBinaries.isNotEmpty) {
      throw ConductorException(
        'Test failed because files found with the wrong entitlements:\n'
        '${wrongEntitlementBinaries.join('\n')}',
      );
    }

    if (unexpectedBinaries.isNotEmpty) {
      throw ConductorException('Test failed because unexpected binaries found in the cache.');
    }

    final String? desiredRevision = argResults![kRevision] as String?;
    if (desiredRevision == null) {
      stdio.printStatus('Verified that binaries are codesigned and have expected entitlements.');
    } else {
      stdio.printStatus(
        'Verified that binaries for commit $desiredRevision are codesigned and have '
        'expected entitlements.',
      );
    }
  }

  List<String>? _allBinaryPaths;

  /// Find every binary file in the given [rootDirectory].
  Future<List<String>> findBinaryPaths(String rootDirectory) async {
    if (_allBinaryPaths != null) {
      return _allBinaryPaths!;
    }
    final List<String> allBinaryPaths = <String>[];
    final io.ProcessResult result = await processManager.run(
      <String>[
        'find',
        rootDirectory,
        '-type',
        'f',
      ],
    );
    final List<String> allFiles = (result.stdout as String)
        .split('\n')
        .where((String s) => s.isNotEmpty)
        .toList();

    await Future.forEach(allFiles, (String filePath) async {
      if (await isBinary(filePath)) {
        allBinaryPaths.add(filePath);
      }
    });
    _allBinaryPaths = allBinaryPaths;
    return _allBinaryPaths!;
  }

  /// Check mime-type of file at [filePath] to determine if it is binary.
  Future<bool> isBinary(String filePath) async {
    final io.ProcessResult result = await processManager.run(
      <String>[
        'file',
        '--mime-type',
        '-b', // is binary
        filePath,
      ],
    );
    return (result.stdout as String).contains('application/x-mach-binary');
  }

  /// Check if the binary has the expected entitlements.
  Future<bool> hasExpectedEntitlements(String binaryPath) async {
    final io.ProcessResult entitlementResult = await processManager.run(
      <String>[
        'codesign',
        '--display',
        '--entitlements',
        ':-',
        binaryPath,
      ],
    );

    if (entitlementResult.exitCode != 0) {
      stdio.printError(
        'The `codesign --entitlements` command failed with exit code ${entitlementResult.exitCode}:\n'
        '${entitlementResult.stderr}\n',
      );
      return false;
    }

    bool passes = true;
    final String output = entitlementResult.stdout as String;
    for (final String entitlement in expectedEntitlements) {
      final bool entitlementExpected =
          (await binariesWithEntitlements).contains(binaryPath);
      if (output.contains(entitlement) != entitlementExpected) {
        stdio.printError(
          'File "$binaryPath" ${entitlementExpected ? 'does not have expected' : 'has unexpected'} '
          'entitlement $entitlement.',
        );
        passes = false;
      }
    }
    return passes;
  }
}
