blob: 7aaa41b19e1a8076d05dd5d912a198d65a82cdcb [file] [log] [blame]
# Copyright 2017 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 Android Java code.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into depot_tools.
This presubmit checks for the following:
- No new calls to Notification.Builder or NotificationCompat.Builder
constructors. Callers should use NotificationWrapperBuilder instead.
- No new calls to AlertDialog.Builder. Callers should use ModalDialogView
instead.
"""
import re
NEW_NOTIFICATION_BUILDER_RE = re.compile(
r'\bnew\sNotification(Compat)?\.Builder\b')
IMPORT_APP_COMPAT_ALERTDIALOG_RE = re.compile(
r'\bimport\sandroid\.support\.v7\.app\.AlertDialog;')
NEW_COMPATIBLE_ALERTDIALOG_BUILDER_RE = re.compile(
r'\bnew\s+(UiUtils\s*\.)?CompatibleAlertDialogBuilder\b')
SPLIT_COMPAT_UTILS_IMPL_NAME_RE = re.compile(
r'\bBundleUtils\.getIdentifierName\(\s*[^\s"]')
COMMENT_RE = re.compile(r'^\s*(//|/\*|\*)')
BROWSER_ROOT = 'chrome/android/java/src/org/chromium/chrome/browser/'
def CheckChangeOnUpload(input_api, output_api):
return _CommonChecks(input_api, output_api)
def CheckChangeOnCommit(input_api, output_api):
return _CommonChecks(input_api, output_api)
def _CommonChecks(input_api, output_api):
"""Checks common to both upload and commit."""
result = []
result.extend(_CheckNotificationConstructors(input_api, output_api))
result.extend(_CheckCompatibleAlertDialogBuilder(input_api, output_api))
result.extend(_CheckBundleUtilsIdentifierName(input_api, output_api))
# Add more checks here
return result
def _CheckNotificationConstructors(input_api, output_api):
files_to_skip = (
'chrome/android/java/src/org/chromium/chrome/browser/notifications/'
'ChromeNotificationWrapperBuilder.java',
'chrome/android/java/src/org/chromium/chrome/browser/notifications/'
'ChromeNotificationWrapperCompatBuilder.java'
)
error_msg = '''
Android Notification Construction Check failed:
Your new code added one or more calls to the Notification.Builder and/or
NotificationCompat.Builder constructors, listed below.
This is banned, please construct notifications using
NotificationWrapperBuilderFactory.createNotificationWrapperBuilder instead,
specifying a channel for use on Android O.
See https://crbug.com/678670 for more information.
'''
return _CheckReIgnoreComment(input_api, output_api, error_msg, files_to_skip,
NEW_NOTIFICATION_BUILDER_RE)
def _CheckCompatibleAlertDialogBuilder(input_api, output_api):
files_to_skip = (
BROWSER_ROOT + 'autofill/keyboard_accessory/'
'AutofillKeyboardAccessoryBridge.java',
BROWSER_ROOT + 'dom_distiller/DistilledPagePrefsView.java',
BROWSER_ROOT + 'dom_distiller/DomDistillerUIUtils.java',
BROWSER_ROOT + 'download/DownloadController.java',
BROWSER_ROOT + 'download/OMADownloadHandler.java',
BROWSER_ROOT + 'externalnav/ExternalNavigationDelegateImpl.java',
BROWSER_ROOT + 'payments/AndroidPaymentApp.java',
BROWSER_ROOT + 'permissions/AndroidPermissionRequester.java',
BROWSER_ROOT + 'share/ShareDelegateImpl.java',
BROWSER_ROOT + 'util/AccessibilityUtil.java',
BROWSER_ROOT + 'webapps/AddToHomescreenDialog.java',
BROWSER_ROOT + 'webapps/WebappOfflineDialog.java',
)
error_msg = '''
Android Use of CompatibleAlertDialogBuilder Check failed:
Your new code added one or more calls to the CompatibleAlertDialogBuilder
constructors, listed below.
We recommend you use ModalDialogProperties to show a dialog whenever possible
to support VR mode. You could only keep the AlertDialog if you are certain
that your new AlertDialog is not used in VR mode (e.g. pereference, FRE)
If you are in doubt, contact
//src/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS
'''
return _CheckReIgnoreComment(input_api, output_api, error_msg, files_to_skip,
NEW_COMPATIBLE_ALERTDIALOG_BUILDER_RE)
def _CheckBundleUtilsIdentifierName(input_api, output_api):
error_msg = '''
BundleUtils.getIdentifierName() not check failed:
BundleUtils.getIdentifierName() must be called with a String literal,
otherwise R8 may not correctly obfuscate the class name passed in.
'''
return _CheckReIgnoreComment(input_api, output_api, error_msg, [],
SPLIT_COMPAT_UTILS_IMPL_NAME_RE)
def _CheckReIgnoreComment(input_api, output_api, error_msg, files_to_skip,
regular_expression, error_files=None):
def CheckLine(current_file, line_number, line, problems, error_files):
"""Returns a boolean whether the line contains an error."""
if (regular_expression.search(line) and not COMMENT_RE.search(line)):
if error_files is not None:
error_files.append(current_file)
problems.append(
' %s:%d\n \t%s' %
(current_file.LocalPath(), line_number, line.strip()))
return True
return False
problems = []
sources = lambda x: input_api.FilterSourceFile(
x, files_to_check=(r'.*\.java$',), files_to_skip=files_to_skip)
for f in input_api.AffectedFiles(include_deletes=False,
file_filter=sources):
previous_line = ''
for line_number, line in enumerate(f.NewContents(), start=1):
if not CheckLine(f, line_number, line, problems, error_files):
if previous_line:
two_lines = '\n'.join([previous_line, line])
CheckLine(f, line_number, two_lines, problems, error_files)
previous_line = line
else:
previous_line = ''
if problems:
return [output_api.PresubmitError(error_msg, problems)]
return []