// 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.localRepoAsUpstream(
      checkouts,
      upstreamPath: flutterRoot.path,
    );
  }

  @override
  String get name => 'codesign';

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

  @override
  void run() {
    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.printError(
          'Warning! When providing an arbitrary revision, the contents of the cache may not');
      stdio.printError(
          'match the expected binaries in the conductor tool. It is preferred to check out');
      stdio.printError(
          'the desired revision and run that version of the conductor.\n');
      revision = argResults![kRevision] as String;
    } else {
      revision = (processManager.runSync(
        <String>['git', 'rev-parse', 'HEAD'],
        workingDirectory: framework.checkoutDirectory.path,
      ).stdout as String)
          .trim();
      assert(revision.isNotEmpty);
    }

    framework.checkout(revision);

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

    verifyExist();
    if (argResults![kSignatures] as bool) {
      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.
  List<String> get binariesWithEntitlements {
    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-release/gen_snapshot',
      'artifacts/engine/darwin-x64/flutter_tester',
      'artifacts/engine/darwin-x64/gen_snapshot',
      'artifacts/engine/ios-profile/gen_snapshot_arm64',
      'artifacts/engine/ios-profile/gen_snapshot_armv7',
      'artifacts/engine/ios-release/gen_snapshot_arm64',
      'artifacts/engine/ios-release/gen_snapshot_armv7',
      'artifacts/engine/ios/gen_snapshot_arm64',
      'artifacts/engine/ios/gen_snapshot_armv7',
      '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',
    ]
        .map((String relativePath) =>
            fileSystem.path.join(framework.cacheDirectory, 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.
  List<String> get binariesWithoutEntitlements {
    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/ios-profile/Flutter.xcframework/ios-armv7_arm64/Flutter.framework/Flutter',
      'artifacts/engine/ios-profile/Flutter.xcframework/ios-x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/engine/ios-release/Flutter.xcframework/ios-armv7_arm64/Flutter.framework/Flutter',
      'artifacts/engine/ios-release/Flutter.xcframework/ios-x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/engine/ios/Flutter.xcframework/ios-armv7_arm64/Flutter.framework/Flutter',
      'artifacts/engine/ios/Flutter.xcframework/ios-x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/ios-deploy/ios-deploy',
    ]
        .map((String relativePath) =>
            fileSystem.path.join(framework.cacheDirectory, 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
  void verifyExist() {
    final Set<String> foundFiles = <String>{};
    for (final String binaryPath in findBinaryPaths(framework.cacheDirectory)) {
      if (binariesWithEntitlements.contains(binaryPath)) {
        foundFiles.add(binaryPath);
      } else if (binariesWithoutEntitlements.contains(binaryPath)) {
        foundFiles.add(binaryPath);
      } else {
        throw ConductorException(
            'Found unexpected binary in cache: $binaryPath');
      }
    }

    final List<String> allExpectedFiles =
        binariesWithEntitlements + 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');
      stdio.printError(
          'If this commit is removing binaries from the cache, this test should be fixed by');
      stdio.printError(
          'removing the relevant entry from either the `binariesWithEntitlements` or');
      stdio.printError(
          '`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
  void verifySignatures() {
    final List<String> unsignedBinaries = <String>[];
    final List<String> wrongEntitlementBinaries = <String>[];
    final List<String> unexpectedBinaries = <String>[];

    for (final String binaryPath in findBinaryPaths(framework.cacheDirectory)) {
      bool verifySignature = false;
      bool verifyEntitlements = false;
      if (binariesWithEntitlements.contains(binaryPath)) {
        verifySignature = true;
        verifyEntitlements = true;
      }
      if (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 = processManager.runSync(
        <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 (!hasExpectedEntitlements(binaryPath)) {
          wrongEntitlementBinaries.add(binaryPath);
        }
      }
    }

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

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

    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.');
    }

    stdio.printStatus(
        'Verified that binaries for commit ${argResults![kRevision] as String} are codesigned and have '
        'expected entitlements.');
  }

  List<String>? _allBinaryPaths;

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

  /// Check mime-type of file at [filePath] to determine if it is binary.
  bool isBinary(String filePath) {
    final io.ProcessResult result = processManager.runSync(
      <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.
  bool hasExpectedEntitlements(String binaryPath) {
    final io.ProcessResult entitlementResult = processManager.runSync(
      <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 =
          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;
  }
}
