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

/// 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',
  '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:html'
  show HtmlElement;
import 'dart:async';
import 'package:ui/ui.dart'
  as ui;
''',
      );
      expect(result.failed, isTrue);
      expect(result.violations, <String>[
        "on line 1: import is broken up into multiple lines: import 'dart:html'",
        "on line 4: 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;
}
