// 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-arm64_armv7/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_armv7/Flutter.framework/Flutter',
      'artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter',
      'artifacts/engine/ios/Flutter.xcframework/ios-arm64_armv7/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(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(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.');
    }

    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;
  }
}
