// Copyright 2013 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.

// ignore_for_file: avoid_print

// Checks that JavaScript API is accessed properly.
//
// JavaScript access needs to be audited to make sure it follows security best
// practices. To do that, all JavaScript access is consolidated into a small
// number of libraries that change infrequently. These libraries are manually
// audited on every change. All other code accesses JavaScript through these
// libraries and does not require audit.

import 'dart:io';

import 'package:test/test.dart';

// Libraries that allow making arbitrary calls to JavaScript.
const List<String> _jsAccessLibraries = <String>[
  'dart:js_util',
  'package:js',
];

// Libraries that are allowed to make direct calls to JavaScript. These
// libraries must be reviewed carefully to make sure JavaScript APIs are used
// safely.
const List<String> _auditedLibraries = <String>[
  'lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart',
  'lib/web_ui/lib/src/engine/safe_browser_api.dart',
];

Future<void> main(List<String> args) async {
  bool areAssertionsEnabled = false;
  assert(() {
    areAssertionsEnabled = true;
    return true;
  }());

  if (!areAssertionsEnabled) {
    throw ArgumentError(
      'This test must run with --enable-asserts',
    );
  }

  test('Self-test', () {
    // A library that doesn't directly access JavaScript API should pass.
    {
      final _CheckResult result = _checkFile(
          File('lib/web_ui/lib/src/engine/alarm_clock.dart'),
'''
// A comment
import 'dart:async';
import 'package:ui/ui.dart' as ui;
export 'foo.dart';
''',
      );
      expect(result.passed, isTrue);
      expect(result.failed, isFalse);
      expect(result.violations, isEmpty);
    }

    // Multi-line imports should fail.
    {
      final _CheckResult result = _checkFile(
          File('lib/web_ui/lib/src/engine/alarm_clock.dart'),
'''
import 'dart:async';
import 'package:ui/ui.dart'
  as ui;
''',
      );
      expect(result.failed, isTrue);
      expect(result.violations, <String>[
        "on line 2: import is broken up into multiple lines: import 'package:ui/ui.dart'",
      ]);
    }

    // A library that doesn't directly access JavaScript API should pass.
    expect(
      _checkFile(
        File('lib/web_ui/lib/src/engine/alarm_clock.dart'),
'''
import 'dart:async';
import 'package:ui/ui.dart' as ui;
''',
      ).passed,
      isTrue,
    );

    // A non-audited library that directly accesses JavaScript API should fail.
    for (final String jsAccessLibrary in _jsAccessLibraries) {
      final _CheckResult result = _checkFile(
          File('lib/web_ui/lib/src/engine/alarm_clock.dart'),
  '''
  import 'dart:async';
  import 'package:ui/ui.dart' as ui;
  import '$jsAccessLibrary';
  ''',
      );
      expect(result.passed, isFalse);
      expect(result.failed, isTrue);
      expect(result.violations, <String>[
        'on line 3: library accesses $jsAccessLibrary directly',
      ]);
    }

    // Audited libraries that directly accesses JavaScript API should pass.
    for (final String auditedLibrary in _auditedLibraries) {
      for (final String jsAccessLibrary in _jsAccessLibraries) {
        expect(
          _checkFile(
            File(auditedLibrary),
    '''
    import 'dart:async';
    import 'package:ui/ui.dart' as ui;
    import '$jsAccessLibrary';
    ''',
          ).passed,
          isTrue,
        );
      }
    }
  });

  test('Check JavaScript access', () async {
    final Directory webUiLibDir = Directory('lib/web_ui/lib');
    final List<File> dartFiles = webUiLibDir
      .listSync(recursive: true)
      .whereType<File>()
      .where((File file) => file.path.endsWith('.dart'))
      .toList();

    expect(dartFiles, isNotEmpty);

    final List<_CheckResult> results = <_CheckResult>[];
    for (final File dartFile in dartFiles) {
      results.add(_checkFile(
        dartFile,
        await dartFile.readAsString(),
      ));
    }

    if (results.any((_CheckResult result) => result.failed)) {
      // Sort to show failures last.
      results.sort((_CheckResult a, _CheckResult b) {
        final int aSortKey = a.passed ? 1 : 0;
        final int bSortKey = b.passed ? 1 : 0;
        return bSortKey - aSortKey;
      });
      int passedCount = 0;
      int failedCount = 0;
      for (final _CheckResult result in results) {
        if (result.passed) {
          passedCount += 1;
          print('PASSED: ${result.file.path}');
        } else {
          failedCount += 1;
          print('FAILED: ${result.file.path}');
          for (final String violation in result.violations) {
            print('        $violation');
          }
        }
      }
      expect(passedCount + failedCount, dartFiles.length);
      print('$passedCount files passed. $failedCount files contain violations.');
      fail('Some file contain violations. See log messages above for details.');
    }
  });
}

_CheckResult _checkFile(File dartFile, String code) {
  final List<String> violations = <String>[];
  final List<String> lines = code.split('\n');
  for (int i = 0; i < lines.length; i += 1) {
    final int lineNumber = i + 1;
    final String line = lines[i].trim();
    final bool isImport = line.startsWith('import');
    if (!isImport) {
      continue;
    }

    final bool isProperlyFormattedImport = line.endsWith(';');
    if (!isProperlyFormattedImport) {
      violations.add('on line $lineNumber: import is broken up into multiple lines: $line');
      continue;
    }

    if (line.contains('"')) {
      violations.add('on line $lineNumber: import is using double quotes instead of single quotes: $line');
      continue;
    }

    final bool isAuditedLibrary = _auditedLibraries.contains(dartFile.path);

    if (isAuditedLibrary) {
      // This library is allowed to access JavaScript API directly.
      continue;
    }

    for (final String jsAccessLibrary in _jsAccessLibraries) {
      if (line.contains("'$jsAccessLibrary'")) {
        violations.add('on line $lineNumber: library accesses $jsAccessLibrary directly');
        continue;
      }
    }
  }

  if (violations.isEmpty) {
    return _CheckResult.passed(dartFile);
  } else {
    return _CheckResult.failed(dartFile, violations);
  }
}

class _CheckResult {
  _CheckResult.passed(this.file) : violations = const <String>[];

  _CheckResult.failed(this.file, this.violations) : assert(violations.isNotEmpty);

  /// The Dart file that was checked.
  final File file;

  /// If the check failed, contains the descriptions of violations.
  ///
  /// If the check passed, this is empty.
  final List<String> violations;

  /// Whether the file passed the check.
  bool get passed => violations.isEmpty;

  /// Whether the file failed the check.
  bool get failed => !passed;
}
