# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Presubmit script for Chromium browser code."""


import re

# Checks whether an autofill-related browsertest fixture class inherits from
# either InProcessBrowserTest or AndroidBrowserTest without having a member of
# type `autofill::test::AutofillBrowserTestEnvironment`. In that case, the
# functions registers a presubmit warning.
def _CheckNoAutofillBrowserTestsWithoutAutofillBrowserTestEnvironment(
        input_api, output_api):
  autofill_files_pattern = re.compile(
      r'(autofill|password_manager).*\.(mm|cc|h)')
  concerned_files = [(f, input_api.ReadFile(f))
                     for f in input_api.AffectedFiles(include_deletes=False)
                     if autofill_files_pattern.search(f.LocalPath())]

  warning_files = []
  class_name = r'^( *)(class|struct)\s+\w+\s*:\s*'
  target_base = r'[^\{]*\bpublic\s+(InProcess|Android)BrowserTest[^\{]*\{'
  class_declaration_pattern = re.compile(
      class_name + target_base, re.MULTILINE)
  for autofill_file, file_content in concerned_files:
    for class_match in re.finditer(class_declaration_pattern, file_content):
      indentation = class_match.group(1)
      class_end_pattern = re.compile(
          r'^' + indentation + r'\};$', re.MULTILINE)
      class_end = class_end_pattern.search(file_content[class_match.start():])

      corresponding_subclass = (
          '' if class_end is None else
          file_content[
              class_match.start():
              class_match.start() + class_end.end()])

      required_member_pattern = re.compile(
          r'^' + indentation +
          r'  (::)?(autofill::)?test::AutofillBrowserTestEnvironment\s+\w+_;',
          re.MULTILINE)
      if not required_member_pattern.search(corresponding_subclass):
        warning_files.append(autofill_file)

  return [output_api.PresubmitPromptWarning(
      'Consider adding a member autofill::test::AutofillBrowserTestEnvironment '
      'to the test fixtures that derive from InProcessBrowserTest or '
      'AndroidBrowserTest in order to disable kAutofillServerCommunication in '
      'browser tests.',
      warning_files)] if len(warning_files) else []

def _RunHistogramChecks(input_api, output_api, histogram_name):
  try:
    # Setup sys.path so that we can call histograms code.
    import sys
    original_sys_path = sys.path
    sys.path = sys.path + [input_api.os_path.join(
        input_api.change.RepositoryRoot(),
        'tools', 'metrics', 'histograms')]

    results = []

    import presubmit_bad_message_reasons
    results.extend(presubmit_bad_message_reasons.PrecheckBadMessage(input_api,
        output_api, histogram_name))

    return results
  except:
    return [output_api.PresubmitError('Could not verify histogram!')]
  finally:
    sys.path = original_sys_path


def _CheckUnwantedDependencies(input_api, output_api):
  problems = []
  for f in input_api.AffectedFiles():
    if not f.LocalPath().endswith('DEPS'):
      continue

    for line_num, line in f.ChangedContents():
      if not line.strip().startswith('#'):
        m = re.search(r".*\/blink\/public\/web.*", line)
        if m:
          problems.append(m.group(0))

  if not problems:
    return []
  return [output_api.PresubmitPromptWarning(
      'chrome/browser cannot depend on blink/public/web interfaces. ' +
      'Use blink/public/common instead.',
      items=problems)]


def _CheckNoInteractiveUiTestLibInNonInteractiveUiTest(input_api, output_api):
  """Makes sure that ui_controls related API are used only in
  interactive_in_tests.
  """
  problems = []
  # There are interactive tests whose name ends with `_browsertest.cc`
  # or `_browser_test.cc`.
  files_to_skip = ((r'.*interactive_.*test\.cc',) +
                   input_api.DEFAULT_FILES_TO_SKIP)
  def FileFilter(affected_file):
    """Check non interactive_uitests only."""
    return input_api.FilterSourceFile(
        affected_file,
        files_to_check=(
            r'.*browsertest\.cc',
            r'.*unittest\.cc'),
        files_to_skip=files_to_skip)

  ui_controls_includes =(
    input_api.re.compile(
        r'#include.*/(ui_controls.*h|interactive_test_utils.h)"'))

  for f in input_api.AffectedFiles(include_deletes=False,
                                   file_filter=FileFilter):
    for line_num, line in f.ChangedContents():
      m = re.search(ui_controls_includes, line)
      if m:
        problems.append('  %s:%d:%s' % (f.LocalPath(), line_num, m.group(0)))

  if not problems:
    return []

  WARNING_MSG ="""
  ui_controls API can be used only in interactive_ui_tests.
  If the test is in the interactive_ui_tests, please consider renaming
  to xxx_interactive_uitest.cc"""
  return [output_api.PresubmitPromptWarning(WARNING_MSG, items=problems)]


def _CheckForUselessExterns(input_api, output_api):
  """Makes sure developers don't copy "extern const char kFoo[]" from
  foo.h to foo.cc.
  """
  problems = []
  BAD_PATTERN = input_api.re.compile(r'^extern const')

  def FileFilter(affected_file):
    """Check only a particular list of files"""
    return input_api.FilterSourceFile(
        affected_file,
        files_to_check=[r'chrome[/\\]browser[/\\]flag_descriptions\.cc']);

  for f in input_api.AffectedFiles(include_deletes=False,
                                   file_filter=FileFilter):
    for _, line in f.ChangedContents():
      if BAD_PATTERN.search(line):
        problems.append(f)

  if not problems:
    return []

  WARNING_MSG ="""Do not write "extern const char" in these .cc files:"""
  return [output_api.PresubmitPromptWarning(WARNING_MSG, items=problems)]


def _CommonChecks(input_api, output_api):
  """Checks common to both upload and commit."""
  results = []
  results.extend(
    _CheckNoAutofillBrowserTestsWithoutAutofillBrowserTestEnvironment(
        input_api, output_api))
  results.extend(_CheckUnwantedDependencies(input_api, output_api))
  results.extend(_RunHistogramChecks(input_api, output_api,
                 "BadMessageReasonChrome"))
  results.extend(_CheckNoInteractiveUiTestLibInNonInteractiveUiTest(
      input_api, output_api))
  results.extend(_CheckForUselessExterns(input_api, output_api))
  return results

def CheckChangeOnUpload(input_api, output_api):
  return _CommonChecks(input_api, output_api)

def CheckChangeOnCommit(input_api, output_api):
  return _CommonChecks(input_api, output_api)
