Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /PRESUBMIT.py
blob: 8c6b8c0475b9a033c0584fe5cbba5b0a7d66708e [file] [log] [blame]
Avi Drissman24976592022-09-12 15:24:31[diff] [blame]1# Copyright 2012 The Chromium Authors
maruel@chromium.orgca8d19842009-02-19 16:33:12[diff] [blame]2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
maruel@chromium.orgca8d19842009-02-19 16:33:12[diff] [blame]4"""Top-level presubmit script for Chromium.
5
Daniel Chengd88244472022-05-16 09:08:47[diff] [blame]6See https://www.chromium.org/developers/how-tos/depottools/presubmit-scripts/
tfarina78bb92f42015-01-31 00:20:48[diff] [blame]7for more details about the presubmit API built into depot_tools.
maruel@chromium.orgca8d19842009-02-19 16:33:12[diff] [blame]8"""
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]9
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]10from typingimportCallable
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]11from typingimportOptional
12from typingimportSequence
mikt19226ff22024-08-27 05:28:21[diff] [blame]13from typingimportTuple
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]14from dataclassesimport dataclass
15
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]16PRESUBMIT_VERSION='2.0.0'
joi@chromium.orgeea609a2011-11-18 13:10:12[diff] [blame]17
maruel@chromium.org379e7dd2010-01-28 17:39:21[diff] [blame]18_EXCLUDED_PATHS=(
Bruce Dawson7f8566b2022-05-06 16:22:18[diff] [blame]19# Generated file
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]20(r"chrome/android/webapk/shell_apk/src/org/chromium"
21 r"/webapk/lib/runtime_library/IWebApkApi.java"),
Mila Greene3aa7222021-09-07 16:34:08[diff] [blame]22# File needs to write to stdout to emulate a tool it's replacing.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]23 r"chrome/updater/mac/keystone/ksadmin.mm",
Ilya Shermane8a7d2d2020-07-25 04:33:47[diff] [blame]24# Generated file.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]25(r"^components/variations/proto/devtools/"
Ilya Shermanc167a962020-08-18 18:40:26[diff] [blame]26 r"client_variations.js"),
Bruce Dawson3bd976c2022-05-06 22:47:52[diff] [blame]27# These are video files, not typescript.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]28 r"^media/test/data/.*.ts",
29 r"^native_client_sdksrc/build_tools/make_rules.py",
30 r"^native_client_sdk/src/build_tools/make_simple.py",
31 r"^native_client_sdk/src/tools/.*.mk",
32 r"^net/tools/spdyshark/.*",
33 r"^skia/.*",
34 r"^third_party/blink/.*",
35 r"^third_party/breakpad/.*",
Darwin Huangd74a9d32019-07-17 17:58:46[diff] [blame]36# sqlite is an imported third party dependency.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]37 r"^third_party/sqlite/.*",
38 r"^v8/.*",
maruel@chromium.org3e4eb112011-01-18 03:29:54[diff] [blame]39 r".*MakeFile$",
gman@chromium.org1084ccc2012-03-14 03:22:53[diff] [blame]40 r".+_autogen\.h$",
Yue Shecf1380552022-08-23 20:59:20[diff] [blame]41 r".+_pb2(_grpc)?\.py$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]42 r".+/pnacl_shim\.c$",
43 r"^gpu/config/.*_list_json\.cc$",
44 r"tools/md_browser/.*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:14[diff] [blame]45# Test pages for Maps telemetry tests.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]46 r"tools/perf/page_sets/maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:54[diff] [blame]47# Test pages for WebRTC telemetry tests.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]48 r"tools/perf/page_sets/webrtc_cases.*",
dpapad2efd4452023-04-06 01:43:45[diff] [blame]49# Test file compared with generated output.
50 r"tools/polymer/tests/html_to_wrapper/.*.html.ts$",
dpapada45be36c2024-08-07 20:19:35[diff] [blame]51# Third-party dependency frozen at a fixed version.
52 r"chrome/test/data/webui/chromeos/chai_v4.js$",
maruel@chromium.org4306417642009-06-11 00:33:40[diff] [blame]53)
maruel@chromium.orgca8d19842009-02-19 16:33:12[diff] [blame]54
John Abd-El-Malek759fea62021-03-13 03:41:14[diff] [blame]55_EXCLUDED_SET_NO_PARENT_PATHS=(
56# It's for historical reasons that blink isn't a top level directory, where
57# it would be allowed to have "set noparent" to avoid top level owners
58# accidentally +1ing changes.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]59'third_party/blink/OWNERS',)
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]60
joi@chromium.org06e6d0ff2012-12-11 01:36:44[diff] [blame]61# Fragment of a regular expression that matches C++ and Objective-C++
62# implementation files.
63_IMPLEMENTATION_EXTENSIONS= r'\.(cc|cpp|cxx|mm)$'
64
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]65# Fragment of a regular expression that matches C++ and Objective-C++
66# header files.
67_HEADER_EXTENSIONS= r'\.(h|hpp|hxx)$'
68
Aleksey Khoroshilov9b28c032022-06-03 16:35:32[diff] [blame]69# Paths with sources that don't use //base.
70_NON_BASE_DEPENDENT_PATHS=(
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]71 r"^chrome/browser/browser_switcher/bho/",
72 r"^tools/win/",
Aleksey Khoroshilov9b28c032022-06-03 16:35:32[diff] [blame]73)
74
joi@chromium.org06e6d0ff2012-12-11 01:36:44[diff] [blame]75# Regular expression that matches code only used for test binaries
76# (best effort).
77_TEST_CODE_EXCLUDED_PATHS=(
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]78 r'.*/(fake_|test_|mock_).+%s'% _IMPLEMENTATION_EXTENSIONS,
Marijn Kruisselbrink2a2d5fc2024-05-15 15:23:49[diff] [blame]79# Test support files, like:
80# foo_test_support.cc
81# bar_test_util_linux.cc (suffix)
82# baz_test_base.cc
83 r'.+_test_(base|support|util)(_[a-z]+)?%s'% _IMPLEMENTATION_EXTENSIONS,
James Cook1b4dc132021-03-09 22:45:13[diff] [blame]84# Test suite files, like:
85# foo_browsertest.cc
86# bar_unittest_mac.cc (suffix)
87# baz_unittests.cc (plural)
88 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(s)?(_[a-z]+)?%s'%
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]89 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:18[diff] [blame]90 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s'% _IMPLEMENTATION_EXTENSIONS,
Victor Hugo Vianna Silvac22e0202021-06-09 19:46:21[diff] [blame]91 r'.+sync_service_impl_harness%s'% _IMPLEMENTATION_EXTENSIONS,
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]92 r'.*/(test|tool(s)?)/.*',
danakj89f47082020-09-02 17:53:43[diff] [blame]93# content_shell is used for running content_browsertests.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]94 r'content/shell/.*',
danakj89f47082020-09-02 17:53:43[diff] [blame]95# Web test harness.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]96 r'content/web_test/.*',
darin@chromium.org7b054982013-11-27 00:44:47[diff] [blame]97# Non-production example code.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]98 r'mojo/examples/.*',
lliabraa@chromium.org8176de12014-06-20 19:07:08[diff] [blame]99# Launcher for running iOS tests on the simulator.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]100 r'testing/iossim/iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:41[diff] [blame]101# EarlGrey app side code for tests.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]102 r'ios/.*_app_interface\.mm$',
Allen Bauer0678d772020-05-11 22:25:17[diff] [blame]103# Views Examples code
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]104 r'ui/views/examples/.*',
Austin Sullivan33da70a2020-10-07 15:39:41[diff] [blame]105# Chromium Codelab
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]106 r'codelabs/*')
maruel@chromium.orgca8d19842009-02-19 16:33:12[diff] [blame]107
Daniel Bratell609102be2019-03-27 20:53:21[diff] [blame]108_THIRD_PARTY_EXCEPT_BLINK='third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]109
joi@chromium.orgeea609a2011-11-18 13:10:12[diff] [blame]110_TEST_ONLY_WARNING=(
111'You might be calling functions intended only for testing from\n'
danakj5f6e3b82020-09-10 13:52:55[diff] [blame]112'production code. If you are doing this from inside another method\n'
113'named as *ForTesting(), then consider exposing things to have tests\n'
114'make that same call directly.\n'
115'If that is not possible, you may put a comment on the same line with\n'
116' // IN-TEST \n'
117'to tell the PRESUBMIT script that the code is inside a *ForTesting()\n'
118'method and can be ignored. Do not do this inside production code.\n'
119'The android-binary-size trybot will block if the method exists in the\n'
Yulun Zeng08d7d8c2024-02-01 18:46:54[diff] [blame]120'release apk.\n'
121'Note: this warning might be a false positive (crbug.com/1196548).')
joi@chromium.orgeea609a2011-11-18 13:10:12[diff] [blame]122
123
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]124@dataclass
125classBanRule:
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]126# String pattern. If the pattern begins with a slash, the pattern will be
127# treated as a regular expression instead.
128 pattern: str
129# Explanation as a sequence of strings. Each string in the sequence will be
130# printed on its own line.
mikt19226ff22024-08-27 05:28:21[diff] [blame]131 explanation:Tuple[str,...]
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]132# Whether or not to treat this ban as a fatal error. If unspecified,
133# defaults to true.
134 treat_as_error:Optional[bool]=None
135# Paths that should be excluded from the ban check. Each string is a regular
136# expression that will be matched against the path of the file being checked
137# relative to the root of the source tree.
138 excluded_paths:Optional[Sequence[str]]=None
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]139# If True, surfaces any violation as a Gerrit comment on the CL after
140# running the CQ.
141 surface_as_gerrit_lint:Optional[bool]=None
marja@chromium.orgcf9b78f2012-11-14 11:40:28[diff] [blame]142
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]143
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]144_BANNED_JAVA_IMPORTS:Sequence[BanRule]=(
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]145BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]146'import java.net.URI;',
147('Use org.chromium.url.GURL instead of java.net.URI, where possible.',
148),
149 excluded_paths=(
150(r'net/android/javatests/src/org/chromium/net/'
151 r'AndroidProxySelectorTest\.java'),
152 r'components/cronet/',
153 r'third_party/robolectric/local/',
154),
Michael Thiessen44457642020-02-06 00:24:15[diff] [blame]155),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]156BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]157'import android.annotation.TargetApi;',
158('Do not use TargetApi, use @androidx.annotation.RequiresApi instead. '
159'RequiresApi ensures that any calls are guarded by the appropriate '
160'SDK_INT check. See https://crbug.com/1116486.',),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]161),
162BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]163'import androidx.test.rule.ActivityTestRule;',
164('Do not use ActivityTestRule, use '
165'org.chromium.base.test.BaseActivityTestRule instead.',),
166 excluded_paths=('components/cronet/',),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]167),
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]168BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]169'import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;',
170('Do not use VectorDrawableCompat, use getResources().getDrawable() to '
171'avoid extra indirections. Please also add trace event as the call '
172'might take more than 20 ms to complete.',),
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]173),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]174)
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]175
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]176_BANNED_JAVA_FUNCTIONS:Sequence[BanRule]=(
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]177BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]178'StrictMode.allowThreadDiskReads()',
179('Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
180'directly.',),
181False,
Eric Stevensona9a980972017-09-23 00:04:41[diff] [blame]182),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]183BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]184'StrictMode.allowThreadDiskWrites()',
185('Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
186'directly.',),
187False,
Eric Stevensona9a980972017-09-23 00:04:41[diff] [blame]188),
Daniel Cheng917ce542022-03-15 20:46:57[diff] [blame]189BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]190'.waitForIdleSync()',
191('Do not use waitForIdleSync as it masks underlying issues. There is '
192'almost always something else you should wait on instead.',),
193False,
Michael Thiessen0f2547e2020-07-27 21:55:36[diff] [blame]194),
Ashley Newson09cbd602022-10-26 11:40:14[diff] [blame]195BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]196 r'/(?<!\bsuper\.)(?<!\bIntent )\bregisterReceiver\(',
197('Do not call android.content.Context.registerReceiver (or an override) '
198'directly. Use one of the wrapper methods defined in '
199'org.chromium.base.ContextUtils, such as '
200'registerProtectedBroadcastReceiver, '
201'registerExportedBroadcastReceiver, or '
202'registerNonExportedBroadcastReceiver. See their documentation for '
203'which one to use.',),
204True,
205 excluded_paths=(
206 r'.*Test[^a-z]',
207 r'third_party/',
208'base/android/java/src/org/chromium/base/ContextUtils.java',
209'chromecast/browser/android/apk/src/org/chromium/chromecast/shell/BroadcastReceiverScope.java',
210),
Ashley Newson09cbd602022-10-26 11:40:14[diff] [blame]211),
Ted Chocd5b327b12022-11-05 02:13:22[diff] [blame]212BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]213 r'/(?:extends|new)\s*(?:android.util.)?Property<[A-Za-z.]+,\s*(?:Integer|Float)>',
214('Do not use Property<..., Integer|Float>, but use FloatProperty or '
215'IntProperty because it will avoid unnecessary autoboxing of '
216'primitives.',),
Ted Chocd5b327b12022-11-05 02:13:22[diff] [blame]217),
Peilin Wangbba4a8652022-11-10 16:33:57[diff] [blame]218BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]219'requestLayout()',
220('Layouts can be expensive. Prefer using ViewUtils.requestLayout(), '
221'which emits a trace event with additional information to help with '
222'scroll jank investigations. See http://crbug.com/1354176.',),
223False,
224 excluded_paths=(
225'ui/android/java/src/org/chromium/ui/base/ViewUtils.java',),
Peilin Wangbba4a8652022-11-10 16:33:57[diff] [blame]226),
Ted Chocf40ea9152023-02-14 19:02:39[diff] [blame]227BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]228'ProfileManager.getLastUsedRegularProfile()',
229('Prefer passing in the Profile reference instead of relying on the '
230'static getLastUsedRegularProfile() call. Only top level entry points '
231'(e.g. Activities) should call this method. Otherwise, the Profile '
Vikram Pasupathyb052c892025-07-08 18:10:00[diff] [blame]232'should either be passed in explicitly or retrieved from an existing '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]233'entity with a reference to the Profile (e.g. WebContents).',),
234False,
235 excluded_paths=(r'.*Test[A-Z]?.*\.java',),
Ted Chocf40ea9152023-02-14 19:02:39[diff] [blame]236),
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]237BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]238 r'/(ResourcesCompat|getResources\(\))\.getDrawable\(\)',
239('getDrawable() can be expensive. If you have a lot of calls to '
240'GetDrawable() or your code may introduce janks, please put your calls '
241'inside a trace().',),
242False,
243 excluded_paths=(r'.*Test[A-Z]?.*\.java',),
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]244),
Henrique Nakashimabbf2b262023-03-10 17:21:39[diff] [blame]245BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]246 r'/RecordHistogram\.getHistogram(ValueCount|TotalCount|Samples)ForTesting\(',
247('Raw histogram counts are easy to misuse; for example they don\'t reset '
248'between batched tests. Use HistogramWatcher to check histogram records '
249'instead.',),
250False,
251 excluded_paths=(
252'base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java',
253'base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java',
254),
Henrique Nakashimabbf2b262023-03-10 17:21:39[diff] [blame]255),
Jenna Himawan859865d2025-02-25 22:22:31[diff] [blame]256BanRule(
257 r'/((announceForAccessibility\()|TYPE_ANNOUNCEMENT)',
258('Android 16 deprecates accessibility announcements, characterized by '
259'the use of announceForAccessibility or the dispatch of '
260'TYPE_ANNOUNCEMENT accessibility events. See '
261'https://developer.android.com/about/versions/16/behavior-changes-all#disruptive-a11y'
262' for more details and suggested replacements.',),
263False,
264),
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]265BanRule(
Sirisha Kavuluru042e4772025-07-03 02:41:09[diff] [blame]266 pattern=(r'/((DeviceInfo\.isDesktop\()|IS_DESKTOP_ANDROID)'),
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]267 explanation=(
Sirisha Kavuluru042e4772025-07-03 02:41:09[diff] [blame]268'Do not add new uses of IS_DESKTOP_ANDROID build flag or '
269'DeviceInfo.isDesktop() until you have the approval of tedchoc@ or '
270'twellington@. Background: it is highly important to reduce the '
271'divergence of features across platforms. '
Eric Lokc26a46662025-05-02 01:04:03[diff] [blame]272'Allowances may be granted to only the directories below: '
273'[build/, chrome/, components/, extensions/, infra/, tools/] ',
274'Note: in particular we need to avoid components shared with '
275'WebView.',
276),
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]277 treat_as_error=False,
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]278 surface_as_gerrit_lint=True,
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]279),
Eric Stevensona9a980972017-09-23 00:04:41[diff] [blame]280)
281
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]282_BANNED_JAVASCRIPT_FUNCTIONS:Sequence[BanRule]=(
Clement Yan9b330cb2022-11-17 05:25:29[diff] [blame]283BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]284 r'/\bchrome\.send\b',
285(
286'The use of chrome.send is disallowed in Chrome (context: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/security/handling-messages-from-web-content.md).',
287'Please use mojo instead for new webuis. https://docs.google.com/document/d/1RF-GSUoveYa37eoyZ9EhwMtaIwoW7Z88pIgNZ9YzQi4/edit#heading=h.gkk22wgk6wff',
288),
289True,
290(
291 r'^(?!ash\/webui).+',
292# TODO(crbug.com/1385601): pre-existing violations still need to be
293# cleaned up.
294'ash/webui/common/resources/cr.m.js',
295'ash/webui/common/resources/multidevice_setup/multidevice_setup_browser_proxy.js',
296'ash/webui/common/resources/quick_unlock/lock_screen_constants.ts',
297'ash/webui/common/resources/smb_shares/smb_browser_proxy.js',
298'ash/webui/connectivity_diagnostics/resources/connectivity_diagnostics.ts',
299'ash/webui/diagnostics_ui/resources/diagnostics_browser_proxy.ts',
300'ash/webui/multidevice_debug/resources/logs.js',
301'ash/webui/multidevice_debug/resources/webui.js',
302'ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js',
303'ash/webui/projector_app/resources/app/trusted/projector_browser_proxy.js',
304# TODO(b/301634378): Remove violation exception once Scanning App
305# migrated off usage of `chrome.send`.
306'ash/webui/scanning/resources/scanning_browser_proxy.ts',
307),
308),)
Clement Yan9b330cb2022-11-17 05:25:29[diff] [blame]309
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]310_BANNED_OBJC_FUNCTIONS:Sequence[BanRule]=(
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]311BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]312'addTrackingRect:',
313(
314'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
315'prohibited. Please use CrTrackingArea instead.',
316'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
317),
318False,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]319),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]320BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]321 r'/NSTrackingArea\W',
322(
323'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
324'instead.',
325'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
326),
327False,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]328),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]329BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]330'convertPointFromBase:',
331(
332'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
333'Please use |convertPoint:(point) fromView:nil| instead.',
334'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
335),
336True,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]337),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]338BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]339'convertPointToBase:',
340(
341'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
342'Please use |convertPoint:(point) toView:nil| instead.',
343'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
344),
345True,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]346),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]347BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]348'convertRectFromBase:',
349(
350'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
351'Please use |convertRect:(point) fromView:nil| instead.',
352'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
353),
354True,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]355),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]356BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]357'convertRectToBase:',
358(
359'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
360'Please use |convertRect:(point) toView:nil| instead.',
361'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
362),
363True,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]364),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]365BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]366'convertSizeFromBase:',
367(
368'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
369'Please use |convertSize:(point) fromView:nil| instead.',
370'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
371),
372True,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]373),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]374BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]375'convertSizeToBase:',
376(
377'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
378'Please use |convertSize:(point) toView:nil| instead.',
379'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
380),
381True,
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]382),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]383BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]384 r"/\s+UTF8String\s*]",
385(
386'The use of -[NSString UTF8String] is dangerous as it can return null',
387'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
388'Please use |SysNSStringToUTF8| instead.',
389),
390True,
391 excluded_paths=('^third_party/ocmock/OCMock/',),
jif65398702016-10-27 10:19:48[diff] [blame]392),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]393BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]394 r'__unsafe_unretained',
395(
396'The use of __unsafe_unretained is almost certainly wrong, unless',
397'when interacting with NSFastEnumeration or NSInvocation.',
398'Please use __weak in files build with ARC, nothing otherwise.',
399),
400False,
Sylvain Defresne4cf1d182017-09-18 14:16:34[diff] [blame]401),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]402BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]403'freeWhenDone:NO',
404(
405'The use of "freeWhenDone:NO" with the NoCopy creation of ',
406'Foundation types is prohibited.',
407),
408True,
Avi Drissman7382afa02019-04-29 23:27:13[diff] [blame]409),
Avi Drissman3d243a42023-08-01 16:53:59[diff] [blame]410BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]411'This file requires ARC support.',
412(
413'ARC compilation is default in Chromium; do not add boilerplate to ',
414'files that require ARC.',
415),
416True,
Avi Drissman3d243a42023-08-01 16:53:59[diff] [blame]417),
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]418)
419
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]420_BANNED_IOS_OBJC_FUNCTIONS=(
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]421BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]422 r'/\bTEST[(]',
423('TEST() macro should not be used in Objective-C++ code as it does not ',
424'drain the autorelease pool at the end of the test. Use TEST_F() ',
425'macro instead with a fixture inheriting from PlatformTest (or a ',
426'typedef).'),
427True,
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]428),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]429BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]430 r'/\btesting::Test\b',
431('testing::Test should not be used in Objective-C++ code as it does ',
432'not drain the autorelease pool at the end of the test. Use ',
433'PlatformTest instead.'),
434True,
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]435),
Ewann2ecc8d72022-07-18 07:41:23[diff] [blame]436BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]437' systemImageNamed:',
438('+[UIImage systemImageNamed:] should not be used to create symbols.',
439'Instead use a wrapper defined in:',
440'ios/chrome/browser/shared/ui/symbols/symbol_helpers.h'),
441True,
442 excluded_paths=(
443'ios/chrome/browser/shared/ui/symbols/symbol_helpers.mm',
444'ios/chrome/common',
445# App extensions have restricted dependencies and thus can't use the
446# wrappers.
447 r'^ios/chrome/\w+_extension/',
448),
Ewann2ecc8d72022-07-18 07:41:23[diff] [blame]449),
Sylvain Defresne781b9f92024-12-11 09:36:18[diff] [blame]450BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]451 r'public (RefCounted)?BrowserStateKeyedServiceFactory',
452('KeyedService factories in //ios/chrome/browser should inherit from',
453'(Refcounted)?ProfileKeyedServieFactoryIOS, not directory from',
454'(Refcounted)?BrowserStateKeyedServiceFactory.'),
455 treat_as_error=True,
456 excluded_paths=(
457'ios/components',
458'ios/web_view',
459),
Sylvain Defresne781b9f92024-12-11 09:36:18[diff] [blame]460),
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]461)
462
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]463_BANNED_IOS_EGTEST_FUNCTIONS:Sequence[BanRule]=(BanRule(
464 r'/\bEXPECT_OCMOCK_VERIFY\b',
465('EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
466'it is meant for GTests. Use [mock verify] instead.'),
467True,
468),)
Peter K. Lee6c03ccff2019-07-15 14:40:05[diff] [blame]469
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]470_BANNED_CPP_FUNCTIONS:Sequence[BanRule]=(
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]471BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]472'%#0',
473(
474'Zero-padded values that use "#" to add prefixes don\'t exhibit ',
475'consistent behavior, since the prefix is not prepended for zero ',
476'values. Use "0x%0..." instead.',
477),
478False,
479[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting7c0d98a2023-10-06 15:42:39[diff] [blame]480),
481BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]482 r'/\busing namespace ',
483(
484'Using directives ("using namespace x") are banned by the Google Style',
485'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
486'Explicitly qualify symbols or use using declarations ("using x::foo").',
487),
488True,
489[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting94a56c42019-10-25 21:54:04[diff] [blame]490),
Antonio Gomes07300d02019-03-13 20:59:57[diff] [blame]491# Make sure that gtest's FRIEND_TEST() macro is not used; the
492# FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
493# used instead since that allows for FLAKY_ and DISABLED_ prefixes.
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]494BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]495'FRIEND_TEST(',
496(
497'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
498'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
499),
500False,
501 excluded_paths=(
502"base/gtest_prod_util.h",
503"base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/gtest_prod_util.h",
504),
avi@chromium.org23e6cbc2012-06-16 18:51:20[diff] [blame]505),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]506BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]507'setMatrixClip',
508(
509'Overriding setMatrixClip() is prohibited; ',
510'the base function is deprecated. ',
511),
512True,
513(),
tomhudsone2c14d552016-05-26 17:07:46[diff] [blame]514),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]515BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]516'SkRefPtr',
517('The use of SkRefPtr is prohibited. ','Please use sk_sp<> instead.'),
518True,
519(),
enne@chromium.org52657f62013-05-20 05:30:31[diff] [blame]520),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]521BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]522'SkAutoRef',
523('The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
524'Please use sk_sp<> instead.'),
525True,
526(),
enne@chromium.org52657f62013-05-20 05:30:31[diff] [blame]527),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]528BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]529'SkAutoTUnref',
530('The use of SkAutoTUnref is dangerous because it implicitly ',
531'converts to a raw pointer. Please use sk_sp<> instead.'),
532True,
533(),
enne@chromium.org52657f62013-05-20 05:30:31[diff] [blame]534),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]535BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]536'SkAutoUnref',
537('The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
538'because it implicitly converts to a raw pointer. ',
539'Please use sk_sp<> instead.'),
540True,
541(),
enne@chromium.org52657f62013-05-20 05:30:31[diff] [blame]542),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]543BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]544 r'/HANDLE_EINTR\(.*close',
545('HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
546'descriptor will be closed, and it is incorrect to retry the close.',
547'Either call close directly and ignore its return value, or wrap close',
548'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
549),
550True,
551(),
mark@chromium.orgd89eec82013-12-03 14:10:59[diff] [blame]552),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]553BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]554 r'/IGNORE_EINTR\((?!.*close)',
555(
556'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
557'calls, use HANDLE_EINTR. See http://crbug.com/269623',
558),
559True,
560(
561# Files that #define IGNORE_EINTR.
562 r'^base/posix/eintr_wrapper\.h$',
563 r'^ppapi/tests/test_broker\.cc$',
564),
mark@chromium.orgd89eec82013-12-03 14:10:59[diff] [blame]565),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]566BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]567 r'/v8::Extension\(',
568(
569'Do not introduce new v8::Extensions into the code base, use',
570'gin::Wrappable instead. See http://crbug.com/334679',
571),
572True,
573(r'extensions/renderer/safe_builtins\.*',),
jochen@chromium.orgec5b3f02014-04-04 18:43:43[diff] [blame]574),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]575BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]576'#pragma comment(lib,',
577('Specify libraries to link with in build files and not in the source.',
578),
579True,
580(
581 r'^base/third_party/symbolize/.*',
582 r'^third_party/abseil-cpp/.*',
Victor Hugo Vianna Silvac86846c02025-03-07 06:56:37[diff] [blame]583 r'^third_party/grpc/source/.*',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]584),
jame2d1a952016-04-02 00:27:10[diff] [blame]585),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]586BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]587 r'/base::SequenceChecker\b',
588('Consider using SEQUENCE_CHECKER macros instead of the class directly.',
589),
590False,
591(),
gabd52c912a2017-05-11 04:15:59[diff] [blame]592),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]593BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]594 r'/base::ThreadChecker\b',
595('Consider using THREAD_CHECKER macros instead of the class directly.',
596),
597False,
598(),
gabd52c912a2017-05-11 04:15:59[diff] [blame]599),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]600BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]601 r'/\b(?!(Sequenced|SingleThread))\w*TaskRunner::(GetCurrentDefault|CurrentDefaultHandle)',
602(
603'It is not allowed to call these methods from the subclasses ',
604'of Sequenced or SingleThread task runners.',
605),
606True,
607(),
Sean Maher03efef12022-09-23 22:43:13[diff] [blame]608),
609BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]610 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
611(
612'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
613'deprecated (http://crbug.com/634507). Please avoid converting away',
614'from the Time types in Chromium code, especially if any math is',
615'being done on time values. For interfacing with platform/library',
616'APIs, use base::Time::(From,To)DeltaSinceWindowsEpoch() or',
617'base::{TimeDelta::In}Microseconds(), or one of the other type',
618'converter methods instead. For faking TimeXXX values (for unit',
619'testing only), use TimeXXX() + Microseconds(N). For',
620'other use cases, please contact base/time/OWNERS.',
621),
622False,
623 excluded_paths=(
624"base/time/time.h",
625"base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h",
626),
Yuri Wiitala2f8de5c2017-07-21 00:11:06[diff] [blame]627),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]628BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]629'CallJavascriptFunctionUnsafe',
630(
631"Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
632'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
633'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
634),
635False,
636(
637 r'^content/browser/webui/web_ui_impl\.(cc|h)$',
638 r'^content/public/browser/web_ui\.h$',
639 r'^content/public/test/test_web_ui\.(cc|h)$',
640),
dbeamb6f4fde2017-06-15 04:03:06[diff] [blame]641),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]642BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]643'leveldb::DB::Open',
644(
645'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
646'third_party/leveldatabase/env_chromium.h. It exposes databases to',
647"Chrome's tracing, making their memory usage visible.",
648),
649True,
650(r'^third_party/leveldatabase/.*\.(cc|h)$',),
Gabriel Charette0592c3a2017-07-26 12:02:04[diff] [blame]651),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]652BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]653'leveldb::NewMemEnv',
654(
655'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
656'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
657"to Chrome's tracing, making their memory usage visible.",
658),
659True,
660(r'^third_party/leveldatabase/.*\.(cc|h)$',),
Chris Mumfordc38afb62017-10-09 17:55:08[diff] [blame]661),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]662BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]663'base::ScopedMockTimeMessageLoopTaskRunner',
664(
665'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
666'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
667'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
668'(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
669'with gab@ first if you think you need it)',
670),
671False,
672(),
Eric Stevenson6b47b44c2017-08-30 20:41:57[diff] [blame]673),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]674BanRule(
Peter Kasting5fdcd782025-01-13 14:57:07[diff] [blame]675'\bstd::aligned_(storage|union)\b',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]676('std::aligned_storage and std::aligned_union are deprecated in',
677'C++23. Use an aligned char array instead.'),
Peter Kasting5fdcd782025-01-13 14:57:07[diff] [blame]678True,
679(),
680),
681BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]682'std::regex',
683(
684'Using std::regex adds unnecessary binary size to Chrome. Please use',
685're2::RE2 instead (crbug.com/755321)',
686),
687True,
688[
689# Abseil's benchmarks never linked into chrome.
690'third_party/abseil-cpp/.*_benchmark.cc',
691],
Francois Doray43670e32017-09-27 12:40:38[diff] [blame]692),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]693BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]694 r'/\bstd::sto(i|l|ul|ll|ull)\b',
695(
696'std::sto{i,l,ul,ll,ull}() use exceptions to communicate results. ',
697'Use base::StringTo[U]Int[64]() instead.',
698),
699True,
700[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting991618a62019-06-17 22:00:09[diff] [blame]701),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]702BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]703 r'/\bstd::sto(f|d|ld)\b',
704(
705'std::sto{f,d,ld}() use exceptions to communicate results. ',
706'For locale-independent values, e.g. reading numbers from disk',
707'profiles, use base::StringToDouble().',
708'For user-visible values, parse using ICU.',
709),
710True,
711[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting991618a62019-06-17 22:00:09[diff] [blame]712),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]713BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]714 r'/\bstd::to_string\b',
715(
716'std::to_string() is locale dependent and slower than alternatives.',
717'For locale-independent strings, e.g. writing numbers to disk',
718'profiles, use base::NumberToString().',
719'For user-visible strings, use base::FormatNumber() and',
720'the related functions in base/i18n/number_formatting.h.',
721),
722True,
723[
724# TODO(crbug.com/335672557): Please do not add to this list. Existing
725# uses should removed.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]726"third_party/blink/renderer/core/css/parser/css_proto_converter.cc",
727"third_party/blink/renderer/core/editing/ime/edit_context.cc",
728"third_party/blink/renderer/platform/graphics/bitmap_image_test.cc",
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]729 _THIRD_PARTY_EXCEPT_BLINK
730],
Daniel Bratell69334cc2019-03-26 11:07:45[diff] [blame]731),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]732BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]733 r'/#include <(cctype|ctype\.h|cwctype|wctype.h)>',
734(
735'<cctype>/<ctype.h>/<cwctype>/<wctype.h> are banned. Use',
736'"third_party/abseil-cpp/absl/strings/ascii.h" instead.',
737),
738True,
739[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting6f79b202023-08-09 21:25:41[diff] [blame]740),
741BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]742 r'/\bstd::shared_ptr\b',
743('std::shared_ptr is banned. Use scoped_refptr instead.',),
744True,
745[
746# Needed for interop with third-party library.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]747 r'^third_party/blink/renderer/core/typed_arrays/array_buffer/'+
748 r'array_buffer_contents\.(cc|h)',
749 r'^third_party/blink/renderer/core/typed_arrays/dom_array_buffer\.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]750'^third_party/blink/renderer/bindings/core/v8/'+
751'v8_wasm_response_extensions.cc',
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]752 r'^gin/array_buffer\.(cc|h)',
753 r'^gin/per_isolate_data\.(cc|h)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]754'^chrome/services/sharing/nearby/',
755# Needed for interop with third-party library libunwindstack.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]756 r'^base/profiler/libunwindstack_unwinder_android\.(cc|h)',
757 r'^base/profiler/native_unwinder_android_memory_regions_map_impl.(cc|h)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]758# Needed for interop with third-party boringssl cert verifier
759'^third_party/boringssl/',
760'^net/cert/',
761'^net/tools/cert_verify_tool/',
762'^services/cert_verifier/',
763'^components/certificate_transparency/',
764'^components/media_router/common/providers/cast/certificate/',
Nina Satragnoe447f2d2025-05-08 16:32:19[diff] [blame]765'^components/trusted_vault/',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]766# gRPC provides some C++ libraries that use std::shared_ptr<>.
767'^chromeos/ash/services/libassistant/grpc/',
768'^chromecast/cast_core/grpc',
769'^chromecast/cast_core/runtime/browser',
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]770 r'^ios/chrome/test/earl_grey/chrome_egtest_plugin_client\.(mm|h)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]771# Fuchsia provides C++ libraries that use std::shared_ptr<>.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]772 r'^base/fuchsia/.*\.(cc|h)',
773 r'.*fuchsia.*test\.(cc|h)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]774# Clang plugins have different build config.
775'^tools/clang/plugins/',
776 _THIRD_PARTY_EXCEPT_BLINK
777],# Not an error in third_party folders.
Daniel Bratell609102be2019-03-27 20:53:21[diff] [blame]778),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]779BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]780 r'/\bstd::weak_ptr\b',
781('std::weak_ptr is banned. Use base::WeakPtr instead.',),
782True,
783[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting991618a62019-06-17 22:00:09[diff] [blame]784),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]785BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]786 r'/\blong long\b',
787('long long is banned. Use [u]int64_t instead.',),
788False,# Only a warning since it is already used.
789[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Daniel Bratell609102be2019-03-27 20:53:21[diff] [blame]790),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]791BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]792 r'/\b(absl|std)::any\b',
793(
794'{absl,std}::any are banned due to incompatibility with the component ',
795'build.',
796),
797True,
798# Not an error in third party folders, though it probably should be :)
799[_THIRD_PARTY_EXCEPT_BLINK],
Daniel Chengc05fcc62022-01-12 16:54:29[diff] [blame]800),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]801BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]802 r'/\bstd::bind\b',
803(
804'std::bind() is banned because of lifetime risks. Use ',
805'base::Bind{Once,Repeating}() instead.',
806),
807True,
808[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Daniel Bratell609102be2019-03-27 20:53:21[diff] [blame]809),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]810BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]811(r'/\bstd::(?:'
812 r'linear_congruential_engine|mersenne_twister_engine|'
813 r'subtract_with_carry_engine|discard_block_engine|'
814 r'independent_bits_engine|shuffle_order_engine|'
815 r'minstd_rand0?|mt19937(_64)?|ranlux(24|48)(_base)?|knuth_b|'
816 r'default_random_engine|'
817 r'random_device|'
818 r'seed_seq'
819 r')\b'),
820(
821'STL random number engines and generators are banned. Use the ',
822'helpers in base/rand_util.h instead, e.g. base::RandBytes() or ',
823'base::RandomBitGenerator.'
824'',
825'Please reach out to cxx@chromium.org if the base APIs are ',
826'insufficient for your needs.',
827),
828True,
829[
830# Not an error in third_party folders.
831 _THIRD_PARTY_EXCEPT_BLINK,
832# Various tools which build outside of Chrome.
833 r'testing/libfuzzer',
Steinar H. Gundersone5689e42024-08-07 18:17:19[diff] [blame]834 r'testing/perf/confidence',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]835 r'tools/android/io_benchmark/',
836# Fuzzers are allowed to use standard library random number generators
837# since fuzzing speed + reproducibility is important.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]838 r'.+_fuzzer\.cc$',
839 r'.+_fuzzertest\.cc$',
840# TODO(https://crbug.com/1380528): These are all unsanctioned uses of
841# the standard library's random number generators, and should be
842# migrated to the //base equivalent.
843 r'ash/ambient/model/ambient_topic_queue\.cc',
844 r'base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest\.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]845 r'base/test/launcher/test_launcher\.cc',
846 r'cc/metrics/video_playback_roughness_reporter_unittest\.cc',
847 r'chrome/browser/apps/app_service/metrics/website_metrics\.cc',
848 r'chrome/browser/ash/power/auto_screen_brightness/monotone_cubic_spline_unittest\.cc',
849 r'chrome/browser/ash/printing/zeroconf_printer_detector_unittest\.cc',
850 r'chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl_unittest\.cc',
851 r'chrome/browser/nearby_sharing/contacts/nearby_share_contacts_sorter_unittest\.cc',
852 r'chrome/browser/privacy_budget/mesa_distribution_unittest\.cc',
853 r'chrome/browser/web_applications/test/web_app_test_utils\.cc',
854 r'chrome/browser/web_applications/test/web_app_test_utils\.cc',
855 r'chrome/browser/win/conflicts/module_blocklist_cache_util_unittest\.cc',
856 r'chromeos/ash/components/memory/userspace_swap/swap_storage_unittest\.cc',
857 r'chromeos/ash/components/memory/userspace_swap/userspace_swap\.cc',
858 r'components/metrics/metrics_state_manager\.cc',
859 r'components/omnibox/browser/history_quick_provider_performance_unittest\.cc',
860 r'components/zucchini/disassembler_elf_unittest\.cc',
861 r'content/browser/webid/federated_auth_request_impl\.cc',
862 r'content/browser/webid/federated_auth_request_impl\.cc',
863 r'media/cast/test/utility/udp_proxy\.h',
864 r'sql/recover_module/module_unittest\.cc',
Nicolas Dossou-Gbeteaf9023d2025-04-07 17:44:38[diff] [blame]865 r'components/regional_capabilities/regional_capabilities_utils.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]866# Do not add new entries to this list. If you have a use case which is
867# not satisfied by the current APIs (i.e. you need an explicitly-seeded
868# sequence, or stability of some sort is required), please contact
869# cxx@chromium.org.
870],
Daniel Cheng192683f2022-11-01 20:52:44[diff] [blame]871),
872BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]873 r'/\b(absl,std)::bind_front\b',
874('{absl,std}::bind_front() are banned. Use base::Bind{Once,Repeating}() '
875'instead.',),
876True,
877[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]878),
879BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]880 r'/\bABSL_FLAG\b',
881('ABSL_FLAG is banned. Use base::CommandLine instead.',),
882True,
883[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]884),
885BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]886 r'/\babsl::c_',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]887('Abseil container utilities are banned. Use std::ranges:: instead.',
888),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]889True,
890[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]891),
892BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]893 r'/\babsl::FixedArray\b',
894('absl::FixedArray is banned. Use base::FixedArray instead.',),
895True,
896[
897# base::FixedArray provides canonical access.
898 r'^base/types/fixed_array.h',
899# Not an error in third_party folders.
900 _THIRD_PARTY_EXCEPT_BLINK,
901],
Peter Kasting431239a2023-09-29 03:11:44[diff] [blame]902),
903BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]904 r'/\babsl::FunctionRef\b',
905('absl::FunctionRef is banned. Use base::FunctionRef instead.',),
906True,
907[
908# base::Bind{Once,Repeating} references absl::FunctionRef to disallow
909# interoperability.
910 r'^base/functional/bind_internal\.h',
911# base::FunctionRef is implemented on top of absl::FunctionRef.
912 r'^base/functional/function_ref.*\..+',
913# Not an error in third_party folders.
914 _THIRD_PARTY_EXCEPT_BLINK,
915],
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]916),
917BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]918 r'/\babsl::(Insecure)?BitGen\b',
919('absl random number generators are banned. Use the helpers in '
920'base/rand_util.h instead, e.g. base::RandBytes() or ',
921'base::RandomBitGenerator.'),
922True,
923[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]924),
925BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]926 pattern=r'/\babsl::(optional|nullopt|make_optional)\b',
Peter Kasting3b77a0c2024-08-22 00:22:26[diff] [blame]927 explanation=('absl::optional is banned. Use std::optional instead.',),
928 treat_as_error=True,
929 excluded_paths=[
930 _THIRD_PARTY_EXCEPT_BLINK,
931]),
932BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]933 r'/(\babsl::Span\b|#include <span>|\bstd::span\b)',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]934('absl::Span and std::span are banned. Use base::span instead.',),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]935True,
936[
937# Included for conversions between base and std.
938 r'base/containers/span.h',
939# Test base::span<> compatibility against std::span<>.
940 r'base/containers/span_unittest.cc',
941# //base/numerics can't use base or absl. So it uses std.
942 r'base/numerics/.*'
Lei Zhang1f9d9ec42024-06-20 18:42:27[diff] [blame]943
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]944# Needed to use QUICHE API.
Ciara McMullinc029c8e2024-08-21 14:22:32[diff] [blame]945 r'android_webview/browser/ip_protection/.*',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]946 r'chrome/browser/ip_protection/.*',
947 r'components/ip_protection/.*',
948 r'net/third_party/quiche/overrides/quiche_platform_impl/quiche_stack_trace_impl\.*',
949 r'services/network/web_transport\.cc',
Lei Zhang1f9d9ec42024-06-20 18:42:27[diff] [blame]950
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]951# Not an error in third_party folders.
952 _THIRD_PARTY_EXCEPT_BLINK,
953],
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]954),
955BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]956 r'/\babsl::StatusOr\b',
957('absl::StatusOr is banned. Use base::expected instead.',),
958True,
959[
960# Needed to use liburlpattern API.
961 r'components/url_pattern/.*',
962 r'services/network/shared_dictionary/simple_url_pattern_matcher\.cc',
963 r'third_party/blink/renderer/core/url_pattern/.*',
964 r'third_party/blink/renderer/modules/manifest/manifest_parser\.cc',
Lei Zhang1f9d9ec42024-06-20 18:42:27[diff] [blame]965
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]966# Needed to use QUICHE API.
Ciara McMullinc029c8e2024-08-21 14:22:32[diff] [blame]967 r'android_webview/browser/ip_protection/.*',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]968 r'chrome/browser/ip_protection/.*',
969 r'components/ip_protection/.*',
Victor Vasiliev435ec102025-05-07 08:33:39[diff] [blame]970 r'net/quic/dedicated_web_transport_http3_client\.cc',
Lei Zhang1f9d9ec42024-06-20 18:42:27[diff] [blame]971
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]972# Needed to use MediaPipe API.
973 r'components/media_effects/.*\.cc',
974# Not an error in third_party folders.
975 _THIRD_PARTY_EXCEPT_BLINK
976],
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]977),
978BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]979 r'/\babsl::(StrSplit|StrJoin|StrCat|StrAppend|Substitute|StrContains)\b',
980('Abseil string utilities are banned. Use base/strings instead.',),
981True,
982[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]983),
984BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]985 r'/\babsl::(Mutex|CondVar|Notification|Barrier|BlockingCounter)\b',
986(
987'Abseil synchronization primitives are banned. Use',
988'base/synchronization instead.',
989),
990True,
991[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Peter Kasting4f35bfc2022-10-18 18:39:12[diff] [blame]992),
993BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]994 r'/\babsl::(Duration|Time|TimeZone|CivilDay)\b',
995('Abseil\'s time library is banned. Use base/time instead.',),
996True,
997[
998# Needed to use QUICHE API.
Ciara McMullinc029c8e2024-08-21 14:22:32[diff] [blame]999 r'android_webview/browser/ip_protection/.*',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1000 r'chrome/browser/ip_protection/.*',
1001 r'components/ip_protection/.*',
Lei Zhang1f9d9ec42024-06-20 18:42:27[diff] [blame]1002
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1003# Needed to integrate with //third_party/nearby
1004 r'components/cross_device/nearby/system_clock.cc',
1005 _THIRD_PARTY_EXCEPT_BLINK# Not an error in third_party folders.
1006],
1007),
1008BanRule(
Victor Hugo Vianna Silva6e84e8d42025-03-19 00:32:00[diff] [blame]1009 r'/absl::(bad_variant_access|get|holds_alternative|monostate|variant|'
1010 r'visit)',
1011('Abseil\'s variant library is banned, use std.',),
Victor Hugo Vianna Silvad9139fbe2025-03-19 20:59:08[diff] [blame]1012True,
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1013[_THIRD_PARTY_EXCEPT_BLINK],
Victor Hugo Vianna Silva6e84e8d42025-03-19 00:32:00[diff] [blame]1014),
1015BanRule(
1016 r'/absl::(apply|exchange|forward|in_place|index_sequence|'
1017 r'integer_sequence|make_from_tuple|make_index_sequence|'
1018 r'make_integer_sequence|move)',
1019('Abseil\'s util library is banned, use std.',),
Victor Hugo Vianna Silvad9139fbe2025-03-19 20:59:08[diff] [blame]1020True,
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1021[_THIRD_PARTY_EXCEPT_BLINK],
Victor Hugo Vianna Silva6e84e8d42025-03-19 00:32:00[diff] [blame]1022),
1023BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1024 r'/#include <chrono>',
1025('<chrono> is banned. Use base/time instead.',),
1026True,
1027[
1028# Not an error in third_party folders:
1029 _THIRD_PARTY_EXCEPT_BLINK,
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1030# This uses openscreen API depending on std::chrono.
1031"components/openscreen_platform/task_runner.cc",
1032]),
1033BanRule(
1034 r'/#include <exception>',
1035('Exceptions are banned and disabled in Chromium.',),
1036True,
1037[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
1038),
1039BanRule(
1040 r'/\bstd::function\b',
1041('std::function is banned. Use base::{Once,Repeating}Callback instead.',
1042),
1043True,
1044[
1045# Has tests that template trait helpers don't unintentionally match
1046# std::function.
1047 r'base/functional/callback_helpers_unittest\.cc',
1048# Required to implement interfaces from the third-party perfetto
1049# library.
1050 r'base/tracing/perfetto_task_runner\.cc',
1051 r'base/tracing/perfetto_task_runner\.h',
1052# Needed for interop with the third-party nearby library type
1053# location::nearby::connections::ResultCallback.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1054 r'chrome/services/sharing/nearby/nearby_connections_conversions\.cc'
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1055# Needed for interop with the internal libassistant library.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1056 r'chromeos/ash/services/libassistant/callback_utils\.h',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1057# Needed for interop with Fuchsia fidl APIs.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1058 r'fuchsia_web/webengine/browser/context_impl_browsertest\.cc',
1059 r'fuchsia_web/webengine/browser/cookie_manager_impl_unittest\.cc',
1060 r'fuchsia_web/webengine/browser/media_player_impl_unittest\.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1061# Required to interop with interfaces from the third-party ChromeML
1062# library API.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1063 r'services/on_device_model/ml/chrome_ml_api\.h',
1064 r'services/on_device_model/ml/on_device_model_executor\.cc',
1065 r'services/on_device_model/ml/on_device_model_executor\.h',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1066# Required to interop with interfaces from the third-party perfetto
1067# library.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1068 r'components/tracing/common/etw_consumer_win_unittest\.cc',
1069 r'services/tracing/public/cpp/perfetto/custom_event_recorder\.cc',
1070 r'services/tracing/public/cpp/perfetto/perfetto_traced_process\.cc',
1071 r'services/tracing/public/cpp/perfetto/perfetto_traced_process\.h',
1072 r'services/tracing/public/cpp/perfetto/perfetto_tracing_backend\.cc',
1073 r'services/tracing/public/cpp/perfetto/producer_client\.cc',
1074 r'services/tracing/public/cpp/perfetto/producer_client\.h',
1075 r'services/tracing/public/cpp/perfetto/producer_test_utils\.cc',
1076 r'services/tracing/public/cpp/perfetto/producer_test_utils\.h',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1077# Required for interop with the third-party webrtc library.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1078 r'third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl\.cc',
1079 r'third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl\.h',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1080# TODO(https://crbug.com/1364577): Various uses that should be
1081# migrated to something else.
1082# Should use base::OnceCallback or base::RepeatingCallback.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1083 r'base/allocator/dispatcher/initializer_unittest\.cc',
1084 r'chrome/browser/ash/accessibility/speech_monitor\.cc',
1085 r'chrome/browser/ash/accessibility/speech_monitor\.h',
1086 r'chrome/browser/ash/login/ash_hud_login_browsertest\.cc',
1087 r'chromecast/base/observer_unittest\.cc',
1088 r'chromecast/browser/cast_web_view\.h',
1089 r'chromecast/public/cast_media_shlib\.h',
1090 r'device/bluetooth/floss/exported_callback_manager\.h',
1091 r'device/bluetooth/floss/floss_dbus_client\.h',
1092 r'device/fido/cable/v2_handshake_unittest\.cc',
1093 r'device/fido/pin\.cc',
1094 r'services/tracing/perfetto/test_utils\.h',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1095# Should use base::FunctionRef.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1096 r'chrome/browser/media/webrtc/test_stats_dictionary\.cc',
1097 r'chrome/browser/media/webrtc/test_stats_dictionary\.h',
1098 r'chromeos/ash/services/libassistant/device_settings_controller\.cc',
1099 r'components/browser_ui/client_certificate/android/ssl_client_certificate_request\.cc',
1100 r'components/gwp_asan/client/sampling_malloc_shims_unittest\.cc',
1101 r'content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest\.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1102# Does not need std::function at all.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1103 r'components/omnibox/browser/autocomplete_result\.cc',
1104 r'device/fido/win/webauthn_api\.cc',
1105 r'media/audio/alsa/alsa_util\.cc',
1106 r'media/remoting/stream_provider\.h',
1107 r'sql/vfs_wrapper\.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1108# TODO(https://crbug.com/1364585): Remove usage and exception list
1109# entries.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1110 r'extensions/renderer/api/automation/automation_internal_custom_bindings\.cc',
1111 r'extensions/renderer/api/automation/automation_internal_custom_bindings\.h',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1112# TODO(https://crbug.com/1364579): Remove usage and exception list
1113# entry.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1114 r'ui/views/controls/focus_ring\.h',
Lei Zhang1f9d9ec42024-06-20 18:42:27[diff] [blame]1115
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1116# Various pre-existing uses in //tools that is low-priority to fix.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1117 r'tools/binary_size/libsupersize/viewer/caspian/diff\.cc',
1118 r'tools/binary_size/libsupersize/viewer/caspian/model\.cc',
1119 r'tools/binary_size/libsupersize/viewer/caspian/model\.h',
1120 r'tools/binary_size/libsupersize/viewer/caspian/tree_builder\.h',
1121 r'tools/clang/base_bind_rewriters/BaseBindRewriters\.cpp',
Daniel Chenge5583e3c2022-09-22 00:19:41[diff] [blame]1122
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1123# Not an error in third_party folders.
1124 _THIRD_PARTY_EXCEPT_BLINK
1125],
Daniel Bratell609102be2019-03-27 20:53:21[diff] [blame]1126),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1127BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1128 r'/#include <X11/',
1129('Do not use Xlib. Use xproto (from //ui/gfx/x:xproto) instead.',),
1130True,
1131[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Tom Andersona95e12042020-09-09 23:08:00[diff] [blame]1132),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1133BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1134 r'/\bstd::ratio\b',
1135('std::ratio is banned by the Google Style Guide.',),
1136True,
1137[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45[diff] [blame]1138),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1139BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1140 r'/\bstd::aligned_alloc\b',
1141(
1142'std::aligned_alloc() is not yet allowed (crbug.com/1412818). Use ',
1143'base::AlignedAlloc() instead.',
1144),
1145True,
1146[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting6d77e9d2023-02-09 21:58:18[diff] [blame]1147),
1148BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1149 r'/#include <(barrier|latch|semaphore|stop_token)>',
1150('The thread support library is banned. Use base/synchronization '
1151'instead.',),
1152True,
1153[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting6d77e9d2023-02-09 21:58:18[diff] [blame]1154),
1155BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1156 r'/\bstd::execution::(par|seq)\b',
1157('std::execution::(par|seq) is banned; they do not fit into '
1158' Chrome\'s threading model, and libc++ doesn\'t have full '
mikt19226ff22024-08-27 05:28:21[diff] [blame]1159'support.',),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1160True,
1161[_THIRD_PARTY_EXCEPT_BLINK],
Helmut Januschka7cc8a84f2024-02-07 22:50:41[diff] [blame]1162),
1163BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1164 r'/\bstd::bit_cast\b',
1165('std::bit_cast is banned; use base::bit_cast instead for values and '
1166'standard C++ casting when pointers are involved.',),
1167True,
1168[
1169# Don't warn in third_party folders.
1170 _THIRD_PARTY_EXCEPT_BLINK,
1171# //base/numerics can't use base or absl.
1172 r'base/numerics/.*'
1173],
Avi Drissman70cb7f72023-12-12 17:44:37[diff] [blame]1174),
1175BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1176 r'/\bstd::(c8rtomb|mbrtoc8)\b',
1177('std::c8rtomb() and std::mbrtoc8() are banned.',),
1178True,
1179[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting6d77e9d2023-02-09 21:58:18[diff] [blame]1180),
1181BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1182 r'/\bchar8_t|std::u8string\b',
1183(
1184'char8_t and std::u8string are not yet allowed. Can you use [unsigned]',
1185' char and std::string instead?',
1186),
1187True,
1188[
1189# The demangler does not use this type but needs to know about it.
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]1190 r'base/third_party/symbolize/demangle\.cc',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1191# Don't warn in third_party folders.
1192 _THIRD_PARTY_EXCEPT_BLINK
1193],
Peter Kastinge2c5ee82023-02-15 17:23:08[diff] [blame]1194),
1195BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1196 r'/(\b(co_await|co_return|co_yield)\b|#include <coroutine>)',
1197('Coroutines are not yet allowed (https://crbug.com/1403840).',),
1198True,
1199[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kastinge2c5ee82023-02-15 17:23:08[diff] [blame]1200),
1201BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1202 r'/^\s*(export\s|import\s+["<:\w]|module(;|\s+[:\w]))',
1203('Modules are disallowed for now due to lack of toolchain support.',),
1204True,
1205[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting69357dc2023-03-14 01:34:29[diff] [blame]1206),
1207BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1208 r'/\[\[(\w*::)?no_unique_address\]\]',
1209(
1210'[[no_unique_address]] does not work as expected on Windows ',
1211'(https://crbug.com/1414621). Use NO_UNIQUE_ADDRESS instead.',
1212),
1213True,
1214[
1215# NO_UNIQUE_ADDRESS / PA_NO_UNIQUE_ADDRESS provide canonical access.
1216 r'^base/compiler_specific\.h',
1217 r'^base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific\.h',
1218# Not an error in third_party folders.
1219 _THIRD_PARTY_EXCEPT_BLINK,
1220],
Peter Kasting8bc046d22023-11-14 00:38:03[diff] [blame]1221),
1222BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1223 r'/#include <format>',
1224('<format> is not yet allowed. Use base::StringPrintf() instead.',),
1225True,
1226[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kastinge2c5ee82023-02-15 17:23:08[diff] [blame]1227),
1228BanRule(
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]1229 pattern='std::views',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1230 explanation=('Use of std::views is banned in Chrome. If you need this '
1231'functionality, please contact cxx@chromium.org.',),
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]1232 treat_as_error=True,
1233 excluded_paths=[
1234# Don't warn in third_party folders.
1235 _THIRD_PARTY_EXCEPT_BLINK
1236],
1237),
1238BanRule(
1239# Ban everything except specifically allowlisted constructs.
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]1240 pattern=r'/std::ranges::(?!(?:'+'|'.join((
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]1241# From https://en.cppreference.com/w/cpp/ranges:
1242# Range access
1243'begin',
1244'end',
1245'cbegin',
1246'cend',
1247'rbegin',
1248'rend',
1249'crbegin',
1250'crend',
1251'size',
1252'ssize',
1253'empty',
1254'data',
1255'cdata',
1256# Range primitives
1257'iterator_t',
1258'const_iterator_t',
1259'sentinel_t',
1260'const_sentinel_t',
1261'range_difference_t',
1262'range_size_t',
1263'range_value_t',
1264'range_reference_t',
1265'range_const_reference_t',
1266'range_rvalue_reference_t',
1267'range_common_reference_t',
1268# Dangling iterator handling
1269'dangling',
1270'borrowed_iterator_t',
1271# Banned: borrowed_subrange_t
1272# Range concepts
1273'range',
1274'borrowed_range',
1275'sized_range',
1276'view',
1277'input_range',
1278'output_range',
1279'forward_range',
1280'bidirectional_range',
1281'random_access_range',
1282'contiguous_range',
1283'common_range',
1284'viewable_range',
1285'constant_range',
Michael Tang626d8982025-05-08 23:24:29[diff] [blame]1286# Views
1287'subrange',
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]1288# Banned: Range factories
1289# Banned: Range adaptors
Peter Kastinga7f93752024-10-24 22:15:40[diff] [blame]1290# Incidentally listed on
1291# https://en.cppreference.com/w/cpp/header/ranges:
1292'enable_borrowed_range',
1293'enable_view',
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]1294# From https://en.cppreference.com/w/cpp/algorithm/ranges:
1295# Constrained algorithms: non-modifying sequence operations
1296'all_of',
1297'any_of',
1298'none_of',
1299'for_each',
1300'for_each_n',
1301'count',
1302'count_if',
1303'mismatch',
1304'equal',
1305'lexicographical_compare',
1306'find',
1307'find_if',
1308'find_if_not',
1309'find_end',
1310'find_first_of',
1311'adjacent_find',
1312'search',
1313'search_n',
1314# Constrained algorithms: modifying sequence operations
1315'copy',
1316'copy_if',
1317'copy_n',
1318'copy_backward',
1319'move',
1320'move_backward',
1321'fill',
1322'fill_n',
1323'transform',
1324'generate',
1325'generate_n',
1326'remove',
1327'remove_if',
1328'remove_copy',
1329'remove_copy_if',
1330'replace',
1331'replace_if',
1332'replace_copy',
1333'replace_copy_if',
1334'swap_ranges',
1335'reverse',
1336'reverse_copy',
1337'rotate',
1338'rotate_copy',
1339'shuffle',
1340'sample',
1341'unique',
1342'unique_copy',
1343# Constrained algorithms: partitioning operations
1344'is_partitioned',
1345'partition',
1346'partition_copy',
1347'stable_partition',
1348'partition_point',
1349# Constrained algorithms: sorting operations
1350'is_sorted',
1351'is_sorted_until',
1352'sort',
1353'partial_sort',
1354'partial_sort_copy',
1355'stable_sort',
1356'nth_element',
1357# Constrained algorithms: binary search operations (on sorted ranges)
1358'lower_bound',
1359'upper_bound',
1360'binary_search',
1361'equal_range',
1362# Constrained algorithms: set operations (on sorted ranges)
1363'merge',
1364'inplace_merge',
1365'includes',
1366'set_difference',
1367'set_intersection',
1368'set_symmetric_difference',
1369'set_union',
1370# Constrained algorithms: heap operations
1371'is_heap',
1372'is_heap_until',
1373'make_heap',
1374'push_heap',
1375'pop_heap',
1376'sort_heap',
1377# Constrained algorithms: minimum/maximum operations
1378'max',
1379'max_element',
1380'min',
1381'min_element',
1382'minmax',
1383'minmax_element',
1384'clamp',
1385# Constrained algorithms: permutation operations
1386'is_permutation',
1387'next_permutation',
1388'prev_premutation',
1389# Constrained uninitialized memory algorithms
1390'uninitialized_copy',
1391'uninitialized_copy_n',
1392'uninitialized_fill',
1393'uninitialized_fill_n',
1394'uninitialized_move',
1395'uninitialized_move_n',
1396'uninitialized_default_construct',
1397'uninitialized_default_construct_n',
1398'uninitialized_value_construct',
1399'uninitialized_value_construct_n',
1400'destroy',
1401'destroy_n',
1402'destroy_at',
1403'construct_at',
1404# Return types
1405'in_fun_result',
1406'in_in_result',
1407'in_out_result',
1408'in_in_out_result',
1409'in_out_out_result',
1410'min_max_result',
1411'in_found_result',
Peter Kastingf379c022025-01-13 14:01:00[diff] [blame]1412# From https://en.cppreference.com/w/cpp/header/functional
1413'equal_to',
1414'not_equal_to',
1415'greater',
1416'less',
1417'greater_equal',
1418'less_equal',
danakj91c715bb2024-07-10 13:24:26[diff] [blame]1419# From https://en.cppreference.com/w/cpp/iterator
1420'advance',
1421'distance',
1422'next',
1423'prev',
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]1424# Require a word boundary at the end of negative lookahead
1425# assertion, e.g. to ensure that even though `view` is allowed (and
1426# should not match this regex), `views` is still treated as
1427# disallowed (and matches the regex).
1428))+ r')\b)\w+',
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]1429 explanation=(
1430'Use of range views and associated helpers is banned in Chrome. '
1431'If you need this functionality, please contact cxx@chromium.org.',
1432),
1433 treat_as_error=True,
1434 excluded_paths=[
1435# Don't warn in third_party folders.
1436 _THIRD_PARTY_EXCEPT_BLINK
1437],
Peter Kastinge2c5ee82023-02-15 17:23:08[diff] [blame]1438),
1439BanRule(
Peter Kasting31879d82024-10-07 20:18:39[diff] [blame]1440 r'/#include <regex>',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1441('<regex> is not allowed. Use third_party/re2 instead.',),
Peter Kasting31879d82024-10-07 20:18:39[diff] [blame]1442True,
1443[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
1444),
1445BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1446 r'/#include <source_location>',
1447('<source_location> is not yet allowed. Use base/location.h instead.',
1448),
1449True,
1450[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kastinge2c5ee82023-02-15 17:23:08[diff] [blame]1451),
1452BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1453 r'/\bstd::to_address\b',
1454(
1455'std::to_address is banned because it is not guaranteed to be',
1456'SFINAE-compatible. Use base::to_address from base/types/to_address.h',
1457'instead.',
1458),
1459True,
1460[
1461# Needed in base::to_address implementation.
1462 r'base/types/to_address.h',
1463 _THIRD_PARTY_EXCEPT_BLINK
1464],# Not an error in third_party folders.
Nick Diego Yamanee522ae82024-02-27 04:23:22[diff] [blame]1465),
1466BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1467 r'/#include <syncstream>',
1468('<syncstream> is banned.',),
1469True,
1470[_THIRD_PARTY_EXCEPT_BLINK],# Don't warn in third_party folders.
Peter Kasting6d77e9d2023-02-09 21:58:18[diff] [blame]1471),
1472BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1473 r'/\bRunMessageLoop\b',
1474('RunMessageLoop is deprecated, use RunLoop instead.',),
1475False,
1476(),
Gabriel Charette147335ea2018-03-22 15:59:19[diff] [blame]1477),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1478BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1479'RunAllPendingInMessageLoop()',
1480(
1481"Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
1482"if you're convinced you need this.",
1483),
1484False,
1485(),
Gabriel Charette147335ea2018-03-22 15:59:19[diff] [blame]1486),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1487BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1488'RunAllPendingInMessageLoop(BrowserThread',
1489(
1490'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
1491'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
1492'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
1493'async events instead of flushing threads.',
1494),
1495False,
1496(),
Gabriel Charette147335ea2018-03-22 15:59:19[diff] [blame]1497),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1498BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1499 r'MessageLoopRunner',
1500('MessageLoopRunner is deprecated, use RunLoop instead.',),
1501False,
1502(),
Gabriel Charette147335ea2018-03-22 15:59:19[diff] [blame]1503),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1504BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1505'GetDeferredQuitTaskForRunLoop',
1506(
1507"GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
1508"gab@ if you found a use case where this is the only solution.",
1509),
1510False,
1511(),
Gabriel Charette147335ea2018-03-22 15:59:19[diff] [blame]1512),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1513BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1514'sqlite3_initialize(',
1515(
1516'Instead of calling sqlite3_initialize(), depend on //sql, ',
1517'#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1518),
1519True,
1520(
1521 r'^sql/initialization\.(cc|h)$',
1522 r'^third_party/sqlite/.*\.(c|cc|h)$',
1523),
Victor Costan3653df62018-02-08 21:38:16[diff] [blame]1524),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1525BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1526'CREATE VIEW',
1527(
1528'SQL views are disabled in Chromium feature code',
1529'https://chromium.googlesource.com/chromium/src/+/HEAD/sql#no-views',
1530),
1531True,
1532(
1533 _THIRD_PARTY_EXCEPT_BLINK,
1534# sql/ itself uses views when using memory-mapped IO.
1535 r'^sql/.*',
1536# Various performance tools that do not build as part of Chrome.
1537 r'^infra/.*',
1538 r'^tools/perf.*',
1539 r'.*perfetto.*',
1540),
Austin Sullivand661ab52022-11-16 08:55:15[diff] [blame]1541),
1542BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1543'CREATE VIRTUAL TABLE',
1544(
1545'SQL virtual tables are disabled in Chromium feature code',
1546'https://chromium.googlesource.com/chromium/src/+/HEAD/sql#no-virtual-tables',
1547),
1548True,
1549(
1550 _THIRD_PARTY_EXCEPT_BLINK,
1551# sql/ itself uses virtual tables in the recovery module and tests.
1552 r'^sql/.*',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1553# Various performance tools that do not build as part of Chrome.
1554 r'^tools/perf.*',
1555 r'.*perfetto.*',
1556),
Austin Sullivand661ab52022-11-16 08:55:15[diff] [blame]1557),
1558BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1559'std::random_shuffle',
1560('std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1561'base::RandomShuffle instead.'),
1562True,
1563(),
tzik5de2157f2018-05-08 03:42:47[diff] [blame]1564),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1565BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1566'ios/web/public/test/http_server',
1567('web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1568),
1569False,
1570(),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24[diff] [blame]1571),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1572BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1573'GetAddressOf',
1574('Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
1575'implicated in a few leaks. ReleaseAndGetAddressOf() is safe but ',
1576'operator& is generally recommended. So always use operator& instead. ',
1577'See http://crbug.com/914910 for more conversion guidance.'),
1578True,
1579(),
Robert Liao764c9492019-01-24 18:46:28[diff] [blame]1580),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1581BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1582'SHFileOperation',
1583('SHFileOperation was deprecated in Windows Vista, and there are less ',
1584'complex functions to achieve the same goals. Use IFileOperation for ',
1585'any esoteric actions instead.'),
1586True,
1587(),
Ben Lewisa9514602019-04-29 17:53:05[diff] [blame]1588),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1589BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1590'StringFromGUID2',
1591('StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1592'Use base::win::WStringFromGUID instead.'),
1593True,
1594(r'/base/win/win_util_unittest.cc',),
Cliff Smolinsky81951642019-04-30 21:39:51[diff] [blame]1595),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1596BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1597'StringFromCLSID',
1598('StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1599'Use base::win::WStringFromGUID instead.'),
1600True,
1601(r'/base/win/win_util_unittest.cc',),
Cliff Smolinsky81951642019-04-30 21:39:51[diff] [blame]1602),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1603BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1604'kCFAllocatorNull',
1605(
1606'The use of kCFAllocatorNull with the NoCopy creation of ',
1607'CoreFoundation types is prohibited.',
1608),
1609True,
1610(),
Avi Drissman7382afa02019-04-29 23:27:13[diff] [blame]1611),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1612BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1613'mojo::ConvertTo',
1614('mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1615'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1616'StringTraits if you would like to convert between custom types and',
1617'the wire format of mojom types.'),
1618False,
1619(
1620 r'^fuchsia_web/webengine/browser/url_request_rewrite_rules_manager\.cc$',
1621 r'^fuchsia_web/webengine/url_request_rewrite_type_converters\.cc$',
1622 r'^third_party/blink/.*\.(cc|h)$',
1623 r'^content/renderer/.*\.(cc|h)$',
1624),
Oksana Zhuravlovafd247772019-05-16 16:57:29[diff] [blame]1625),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1626BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1627'GetInterfaceProvider',
1628('InterfaceProvider is deprecated.',
1629'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1630'or Platform::GetBrowserInterfaceBroker.'),
1631False,
1632(),
Oksana Zhuravlovac8222d22019-12-19 19:21:16[diff] [blame]1633),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1634BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1635'CComPtr',
1636('New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1637'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1638'details.'),
1639False,
1640(),
Robert Liao1d78df52019-11-11 20:02:01[diff] [blame]1641),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1642BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1643 r'/\b(IFACE|STD)METHOD_?\(',
1644('IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1645'Instead, always use IFACEMETHODIMP in the declaration.'),
1646False,
1647[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Xiaohan Wang72bd2ba2020-02-18 21:38:20[diff] [blame]1648),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1649BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1650'RemoveAllChildViewsWithoutDeleting',
1651('RemoveAllChildViewsWithoutDeleting is deprecated.',
1652'This method is deemed dangerous as, unless raw pointers are re-added,',
1653'calls to this method introduce memory leaks.'),
1654False,
1655(),
Peter Boström7ff41522021-07-29 03:43:27[diff] [blame]1656),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1657BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1658 r'/\bTRACE_EVENT_ASYNC_',
1659(
1660'Please use TRACE_EVENT_NESTABLE_ASYNC_.. macros instead',
1661'of TRACE_EVENT_ASYNC_.. (crbug.com/1038710).',
1662),
1663False,
1664(
1665 r'^base/trace_event/.*',
1666 r'^base/tracing/.*',
1667),
Eric Secklerbe6f48d2020-05-06 18:09:12[diff] [blame]1668),
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]1669BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1670'RoInitialize',
1671('Improper use of [base::win]::RoInitialize() has been implicated in a ',
1672'few COM initialization leaks. Use base::win::ScopedWinrtInitializer ',
1673'instead. See http://crbug.com/1197722 for more information.'),
1674True,
1675(
1676 r'^base/win/scoped_winrt_initializer\.cc$',
1677 r'^third_party/abseil-cpp/absl/.*',
1678),
Robert Liao22f66a52021-04-10 00:57:52[diff] [blame]1679),
Patrick Monettec343bb982022-06-01 17:18:45[diff] [blame]1680BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1681 r'base::Watchdog',
1682(
1683'base::Watchdog is deprecated because it creates its own thread.',
1684'Instead, manually start a timer on a SequencedTaskRunner.',
1685),
1686False,
1687(),
Patrick Monettec343bb982022-06-01 17:18:45[diff] [blame]1688),
Andrew Rayskiy04a51ce2022-06-07 11:47:09[diff] [blame]1689BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1690'base::Passed',
1691('Do not use base::Passed. It is a legacy helper for capturing ',
1692'move-only types with base::BindRepeating, but invoking the ',
1693'resulting RepeatingCallback moves the captured value out of ',
1694'the callback storage, and subsequent invocations may pass the ',
1695'value in a valid but undefined state. Prefer base::BindOnce().',
1696'See http://crbug.com/1326449 for context.'),
1697False,
1698(
1699# False positive, but it is also fine to let bind internals reference
1700# base::Passed.
1701 r'^base[\\/]functional[\\/]bind\.h',
1702 r'^base[\\/]functional[\\/]bind_internal\.h',
1703),
Andrew Rayskiy04a51ce2022-06-07 11:47:09[diff] [blame]1704),
Daniel Cheng2248b332022-07-27 06:16:59[diff] [blame]1705BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1706 r'base::Feature k',
1707('Please use BASE_DECLARE_FEATURE() or BASE_FEATURE() instead of ',
1708'directly declaring/defining features.'),
1709True,
1710[
1711# Implements BASE_DECLARE_FEATURE().
1712 r'^base/feature_list\.h',
1713],
Daniel Chengba3bc2e2022-10-03 02:45:43[diff] [blame]1714),
Robert Ogden92101dcb2022-10-19 23:49:36[diff] [blame]1715BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1716 r'/\bchartorune\b',
1717('chartorune is not memory-safe, unless you can guarantee the input ',
1718'string is always null-terminated. Otherwise, please use charntorune ',
1719'from libphonenumber instead.'),
1720True,
1721[
1722 _THIRD_PARTY_EXCEPT_BLINK,
1723# Exceptions to this rule should have a fuzzer.
1724],
Robert Ogden92101dcb2022-10-19 23:49:36[diff] [blame]1725),
Arthur Sonzogni1da65fa2023-03-27 16:01:52[diff] [blame]1726BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1727 r'/\b#include "base/atomicops\.h"\b',
1728('Do not use base::subtle atomics, but std::atomic, which are simpler '
1729'to use, have better understood, clearer and richer semantics, and are '
1730'harder to mis-use. See details in base/atomicops.h.',),
1731False,
1732[_THIRD_PARTY_EXCEPT_BLINK],# Not an error in third_party folders.
Benoit Lize79cf0592023-01-27 10:01:57[diff] [blame]1733),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1734BanRule(r'CrossThreadPersistent<',(
Arthur Sonzogni60348572e2023-04-07 10:22:52[diff] [blame]1735'Do not use blink::CrossThreadPersistent, but '
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1736'blink::CrossThreadHandle. It is harder to mis-use.','More info: '
Arthur Sonzogni60348572e2023-04-07 10:22:52[diff] [blame]1737'https://docs.google.com/document/d/1GIT0ysdQ84sGhIo1r9EscF_fFt93lmNVM_q4vvHj2FQ/edit#heading=h.3e4d6y61tgs',
1738'Please contact platform-architecture-dev@ before adding new instances.'
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1739),False,[]),
1740BanRule(r'CrossThreadWeakPersistent<',(
Arthur Sonzogni60348572e2023-04-07 10:22:52[diff] [blame]1741'Do not use blink::CrossThreadWeakPersistent, but '
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1742'blink::CrossThreadWeakHandle. It is harder to mis-use.','More info: '
Arthur Sonzogni60348572e2023-04-07 10:22:52[diff] [blame]1743'https://docs.google.com/document/d/1GIT0ysdQ84sGhIo1r9EscF_fFt93lmNVM_q4vvHj2FQ/edit#heading=h.3e4d6y61tgs',
1744'Please contact platform-architecture-dev@ before adding new instances.'
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1745),False,[]),
1746BanRule(r'objc/objc.h',(
Avi Drissman491617c2023-04-13 17:33:15[diff] [blame]1747'Do not include <objc/objc.h>. It defines away ARC lifetime '
1748'annotations, and is thus dangerous.',
1749'Please use the pimpl pattern; search for `ObjCStorage` for examples.',
1750'For further reading on how to safely mix C++ and Obj-C, see',
1751'https://chromium.googlesource.com/chromium/src/+/main/docs/mac/mixing_cpp_and_objc.md'
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1752),True,[]),
1753BanRule(
1754 r'/#include <filesystem>',
1755('libc++ <filesystem> is banned per the Google C++ styleguide.',),
1756True,
1757# This fuzzing framework is a standalone open source project and
1758# cannot rely on Chromium base.
1759(r'third_party/centipede'),
Avi Drissman491617c2023-04-13 17:33:15[diff] [blame]1760),
Grace Park8d59b54b2023-04-26 17:53:35[diff] [blame]1761BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1762 r'TopDocument()',
1763('TopDocument() does not work correctly with out-of-process iframes. '
1764'Please do not introduce new uses.',),
1765True,
1766(
1767# TODO(crbug.com/617677): Remove all remaining uses.
1768 r'^third_party/blink/renderer/core/dom/document\.cc',
1769 r'^third_party/blink/renderer/core/dom/document\.h',
1770 r'^third_party/blink/renderer/core/dom/element\.cc',
1771 r'^third_party/blink/renderer/core/exported/web_disallow_transition_scope_test\.cc',
1772 r'^third_party/blink/renderer/core/exported/web_document_test\.cc',
1773 r'^third_party/blink/renderer/core/html/html_anchor_element\.cc',
1774 r'^third_party/blink/renderer/core/html/html_dialog_element\.cc',
1775 r'^third_party/blink/renderer/core/html/html_element\.cc',
1776 r'^third_party/blink/renderer/core/html/html_frame_owner_element\.cc',
1777 r'^third_party/blink/renderer/core/html/media/video_wake_lock\.cc',
1778 r'^third_party/blink/renderer/core/loader/anchor_element_interaction_tracker\.cc',
1779 r'^third_party/blink/renderer/core/page/scrolling/root_scroller_controller\.cc',
1780 r'^third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller\.cc',
1781 r'^third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller\.h',
1782 r'^third_party/blink/renderer/core/script/classic_pending_script\.cc',
1783 r'^third_party/blink/renderer/core/script/script_loader\.cc',
1784),
Grace Park8d59b54b2023-04-26 17:53:35[diff] [blame]1785),
Daniel Cheng72153e02023-05-18 21:18:14[diff] [blame]1786BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1787 pattern=r'base::raw_ptr<',
1788 explanation=('Do not use base::raw_ptr, use raw_ptr.',),
1789 treat_as_error=True,
1790 excluded_paths=(
1791'^base/',
1792'^tools/',
1793),
Daniel Cheng72153e02023-05-18 21:18:14[diff] [blame]1794),
Arthur Sonzognif0eea302023-08-18 19:20:31[diff] [blame]1795BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1796 pattern=r'base:raw_ref<',
1797 explanation=('Do not use base::raw_ref, use raw_ref.',),
1798 treat_as_error=True,
1799 excluded_paths=(
1800'^base/',
1801'^tools/',
1802),
Arthur Sonzognif0eea302023-08-18 19:20:31[diff] [blame]1803),
1804BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1805 pattern=r'/raw_ptr<[^;}]*\w{};',
1806 explanation=(
1807'Do not use {} for raw_ptr initialization, use = nullptr instead.',
1808),
1809 treat_as_error=True,
1810 excluded_paths=(
1811'^base/',
1812'^tools/',
1813),
Arthur Sonzognif0eea302023-08-18 19:20:31[diff] [blame]1814),
Anton Maliev66751812023-08-24 16:28:13[diff] [blame]1815BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1816 pattern=r'/#include "base/allocator/.*/raw_'
1817 r'(ptr|ptr_cast|ptr_exclusion|ref).h"',
1818 explanation=(
1819'Please include the corresponding facade headers:',
1820'- #include "base/memory/raw_ptr.h"',
1821'- #include "base/memory/raw_ptr_cast.h"',
1822'- #include "base/memory/raw_ptr_exclusion.h"',
1823'- #include "base/memory/raw_ref.h"',
1824),
1825 treat_as_error=True,
1826 excluded_paths=(
1827'^base/',
1828'^tools/',
1829),
Tom Sepez41eb158d2023-09-12 16:16:22[diff] [blame]1830),
1831BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1832 pattern=r'ContentSettingsType::COOKIES',
1833 explanation=
1834('Do not use ContentSettingsType::COOKIES to check whether cookies are '
1835'supported in the provided context. Instead rely on the '
1836'content_settings::CookieSettings API. If you are using '
1837'ContentSettingsType::COOKIES to check the user preference setting '
1838'specifically, disregard this warning.',),
1839 treat_as_error=False,
1840 excluded_paths=(
1841'^chrome/browser/ui/content_settings/',
1842'^components/content_settings/',
1843'^services/network/cookie_settings.cc',
1844'.*test.cc',
1845),
Arthur Sonzogni48c6aea22023-09-04 22:25:20[diff] [blame]1846),
1847BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1848 pattern=r'ContentSettingsType::TRACKING_PROTECTION',
1849 explanation=
1850('Do not directly use ContentSettingsType::TRACKING_PROTECTION to check '
1851'for tracking protection exceptions. Instead rely on the '
1852'privacy_sandbox::TrackingProtectionSettings API.',),
1853 treat_as_error=False,
1854 excluded_paths=(
1855'^chrome/browser/ui/content_settings/',
1856'^components/content_settings/',
1857'^components/privacy_sandbox/tracking_protection_settings.cc',
1858'.*test.cc',
1859),
Anton Maliev66751812023-08-24 16:28:13[diff] [blame]1860),
Tom Andersoncd522072023-10-03 00:52:35[diff] [blame]1861BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1862 pattern=r'/\bg_signal_connect',
1863 explanation=('Use ScopedGSignal instead of g_signal_connect*()',),
1864 treat_as_error=True,
1865 excluded_paths=('^ui/base/glib/scoped_gsignal.h',),
Michelle Abreo6b7437822024-04-26 17:29:04[diff] [blame]1866),
1867BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1868 pattern=r'features::kIsolatedWebApps',
1869 explanation=(
1870'Do not use `features::kIsolatedWebApps` directly to guard Isolated ',
1871'Web App code. ',
Andrew Rayskiy7ae2b5d2025-02-28 16:59:38[diff] [blame]1872'Use `content::AreIsolatedWebAppsEnabled()` in the browser process '
1873'or check the `kEnableIsolatedWebAppsInRenderer` command line flag '
1874'in the renderer process.',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1875),
1876 treat_as_error=True,
Andrew Rayskiy7ae2b5d2025-02-28 16:59:38[diff] [blame]1877 excluded_paths=_TEST_CODE_EXCLUDED_PATHS+(
1878'^chrome/browser/about_flags.cc',
1879'^chrome/browser/component_updater/iwa_key_distribution_component_installer.cc',
1880'^chrome/browser/web_applications/isolated_web_apps/chrome_content_browser_client_isolated_web_apps_part.cc',
1881'^chrome/browser/ui/startup/bad_flags_prompt.cc',
1882'^content/shell/browser/shell_content_browser_client.cc',
1883)),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1884BanRule(
1885 pattern=r'features::kIsolatedWebAppDevMode',
1886 explanation=(
1887'Do not use `features::kIsolatedWebAppDevMode` directly to guard code ',
1888'related to Isolated Web App Developer Mode. ',
1889'Use `web_app::IsIwaDevModeEnabled()` instead.',
1890),
1891 treat_as_error=True,
1892 excluded_paths=_TEST_CODE_EXCLUDED_PATHS+(
1893'^chrome/browser/about_flags.cc',
1894'^chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.cc',
1895'^chrome/browser/ui/startup/bad_flags_prompt.cc',
1896)),
1897BanRule(
1898 pattern=r'features::kIsolatedWebAppUnmanagedInstall',
1899 explanation=(
1900'Do not use `features::kIsolatedWebAppUnmanagedInstall` directly to ',
1901'guard code related to unmanaged install flow for Isolated Web Apps. ',
1902'Use `web_app::IsIwaUnmanagedInstallEnabled()` instead.',
1903),
1904 treat_as_error=True,
1905 excluded_paths=_TEST_CODE_EXCLUDED_PATHS+(
1906'^chrome/browser/about_flags.cc',
1907'^chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.cc',
1908)),
1909BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1910 pattern='/(CUIAutomation|AccessibleObjectFromWindow)',
1911 explanation=
1912('Direct usage of UIAutomation or IAccessible2 in client code is '
1913'discouraged in Chromium, as it is not an assistive technology and '
1914'should not rely on accessibility APIs directly. These APIs can '
1915'introduce significant performance overhead. However, if you believe '
1916'your use case warrants an exception, please discuss it with an '
1917'accessibility owner before proceeding. For more information on the '
1918'performance implications, see https://docs.google.com/document/d/1jN4itpCe_bDXF0BhFaYwv4xVLsCWkL9eULdzjmLzkuk/edit#heading=h.pwth3nbwdub0.',
1919),
1920 treat_as_error=False,
Andrew Rayskiycdd45e732024-03-20 14:32:39[diff] [blame]1921),
1922BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1923 pattern=r'/WIDGET_OWNS_NATIVE_WIDGET|'
1924 r'NATIVE_WIDGET_OWNS_WIDGET',
1925 explanation=
1926('WIDGET_OWNS_NATIVE_WIDGET and NATIVE_WIDGET_OWNS_WIDGET are in the '
1927'process of being deprecated. Consider using the new '
1928'CLIENT_OWNS_WIDGET ownership model. Eventually, this will be the only '
1929'available ownership model available and the associated enumeration'
1930'will be removed.',),
1931 treat_as_error=False,
Andrew Rayskiycdd45e732024-03-20 14:32:39[diff] [blame]1932),
1933BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1934 pattern='ProfileManager::GetLastUsedProfile',
1935 explanation=
1936('Most code should already be scoped to a Profile. Pass in a Profile* '
Vikram Pasupathyb052c892025-07-08 18:10:00[diff] [blame]1937'or retrieve from an existing entity with a reference to the Profile '
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1938'(e.g. WebContents).',),
1939 treat_as_error=False,
Arthur Sonzogni5cbd3e32024-02-08 17:51:32[diff] [blame]1940),
Helmut Januschkab3f71ab52024-03-12 02:48:05[diff] [blame]1941BanRule(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1942 pattern=(r'/FindBrowserWithUiElementContext|'
1943 r'FindBrowserWithTab|'
1944 r'FindBrowserWithGroup|'
1945 r'FindTabbedBrowser|'
1946 r'FindAnyBrowser|'
1947 r'FindBrowserWithProfile|'
Erik Chen5f02eb4c2024-08-23 06:30:44[diff] [blame]1948 r'FindLastActive|'
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1949 r'FindBrowserWithActiveWindow'),
1950 explanation=
1951('Most code should already be scoped to a Browser. Pass in a Browser* '
Vikram Pasupathyb052c892025-07-08 18:10:00[diff] [blame]1952'or retrieve from an existing entity with a reference to the Browser.',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1953),
1954 treat_as_error=False,
Helmut Januschkab3f71ab52024-03-12 02:48:05[diff] [blame]1955),
1956BanRule(
Tom Sepezd3272cd2025-02-21 19:11:31[diff] [blame]1957 pattern=r'subspan(0u,',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1958 explanation=(
1959'Prefer first(n) over subspan(0u, n) as it is shorter, and the '
1960'compiler may have to emit a branch for the n == dynamic_extent '
1961'case of subspan().',),
Tom Sepezd3272cd2025-02-21 19:11:31[diff] [blame]1962 treat_as_error=False,
1963),
1964BanRule(
Tom Sepezea67b6e2024-08-08 18:17:27[diff] [blame]1965 pattern=r'UNSAFE_TODO(',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1966 explanation=(
1967'Do not use UNSAFE_TODO() to write new unsafe code. Use only when '
1968'removing a pre-existing file-wide allow_unsafe_buffers pragma, or '
1969'when incrementally converting code off of unsafe interfaces',),
Tom Sepezea67b6e2024-08-08 18:17:27[diff] [blame]1970 treat_as_error=False,
1971),
1972BanRule(
Claudio DeSouzaad1d1f252025-04-22 23:38:58[diff] [blame]1973 pattern='#pragma allow_unsafe_buffers',
1974 explanation=
1975('Do not use allow_unsafe_buffers to write new unsafe code. Use only '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1976'when enabling unsafe buffers checks under a new uncovered path.',),
Claudio DeSouzaad1d1f252025-04-22 23:38:58[diff] [blame]1977 treat_as_error=False,
1978),
1979BanRule(
Tom Sepezea67b6e2024-08-08 18:17:27[diff] [blame]1980 pattern=r'UNSAFE_BUFFERS(',
1981 explanation=
Tom Sepeza90f92b2024-08-15 16:01:35[diff] [blame]1982('Try to avoid using UNSAFE_BUFFERS() if at all possible. Otherwise, '
1983'be sure to justify in a // SAFETY comment why other options are not '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1984'available, and why the code is safe.',),
Tom Sepezea67b6e2024-08-08 18:17:27[diff] [blame]1985 treat_as_error=False,
1986),
Erik Chend086ae02024-08-20 22:53:33[diff] [blame]1987BanRule(
1988 pattern='BrowserWithTestWindowTest',
1989 explanation=
1990('Do not use BrowserWithTestWindowTest. By instantiating an instance '
1991'of class Browser, the test is no longer a unit test but is instead a '
1992'browser test. The class BrowserWithTestWindowTest forces production '
1993'logic to take on test-only conditionals, which is an anti-pattern. '
1994'Features should be performing dependency injection rather than '
1995'directly using class Browser. See '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]1996'docs/chrome_browser_design_principles.md for more details.',),
Erik Chend086ae02024-08-20 22:53:33[diff] [blame]1997 treat_as_error=False,
1998),
Erik Chen8cf3a652024-08-23 17:13:30[diff] [blame]1999BanRule(
Erik Chen959cdd72024-08-29 02:11:21[diff] [blame]2000 pattern='TestWithBrowserView',
2001 explanation=
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2002('Do not use TestWithBrowserView. See '
2003'docs/chrome_browser_design_principles.md for details. If you want '
2004'to write a test that has both a Browser and a BrowserView, create '
2005'a browser_test. If you want to write a unit_test, your code must '
2006'not reference Browser*.',),
Erik Chen959cdd72024-08-29 02:11:21[diff] [blame]2007 treat_as_error=False,
2008),
2009BanRule(
Erik Chene89ebe32025-02-22 02:46:49[diff] [blame]2010 pattern='CreateBrowserWithTestWindow',
2011 explanation=
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2012('Do not use CreateBrowserWithTestWindow. See '
2013'docs/chrome_browser_design_principles.md for details. If you want '
2014'to write a test that has a Browser, create a browser_test. If you '
2015'want to write a unit_test, your code must not reference Browser*.',
Erik Chene89ebe32025-02-22 02:46:49[diff] [blame]2016),
2017 treat_as_error=False,
2018),
2019BanRule(
Erik Chenf12a06642025-03-13 23:30:34[diff] [blame]2020 pattern='CreateBrowserWithTestWindowForParams',
2021 explanation=
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2022('Do not use CreateBrowserWithTestWindowForParams. See '
2023'docs/chrome_browser_design_principles.md for details. If you want '
2024'to write a test that has a Browser, create a browser_test and use '
2025'Browser::Browser. If you want to write a unit_test, your code must '
2026'not reference Browser*.',),
Erik Chenf12a06642025-03-13 23:30:34[diff] [blame]2027 treat_as_error=False,
2028),
2029BanRule(
Mikita Kuchyn383c9bab2025-05-23 15:15:23[diff] [blame]2030 pattern='TestBrowserWindow',
2031 explanation=(
2032'Do not use TestBrowserWindow. See '
2033'docs/chrome_browser_design_principles.md for details. If you want '
2034'to write a test that has a Browser, create a browser_test. If you'
2035'want to write a unit_test, your code should not reference Browser'
2036'or BrowserWindow.',
2037),
2038 treat_as_error=False,
2039),
2040BanRule(
Erik Chen8cf3a652024-08-23 17:13:30[diff] [blame]2041 pattern='RunUntilIdle',
2042 explanation=
2043('Do not RunUntilIdle. If possible, explicitly quit the run loop using '
2044'run_loop.Quit() or run_loop.QuitClosure() if completion can be '
2045'observed using a lambda or callback. Otherwise, wait for the '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2046'condition to be true via base::test::RunUntil().',),
Erik Chen8cf3a652024-08-23 17:13:30[diff] [blame]2047 treat_as_error=False,
2048),
Daniel Chengddde13a2024-09-05 21:39:28[diff] [blame]2049BanRule(
2050 pattern=r'/\bstd::(literals|string_literals|string_view_literals)\b',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2051 explanation=(
Daniel Chengddde13a2024-09-05 21:39:28[diff] [blame]2052'User-defined literals are banned by the Google C++ style guide. '
2053'Exceptions are provided in Chrome for string and string_view '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2054'literals that embed \\0.',),
Daniel Chengddde13a2024-09-05 21:39:28[diff] [blame]2055 treat_as_error=True,
2056 excluded_paths=(
2057# Various tests or test helpers that embed NUL in strings or
2058# string_views.
Daniel Chengddde13a2024-09-05 21:39:28[diff] [blame]2059 r'^base/strings/string_util_unittest\.cc',
2060 r'^base/strings/utf_string_conversions_unittest\.cc',
Hidehiko Abe51601812025-01-12 16:17:35[diff] [blame]2061 r'^chromeos/ash/experiences/arc/session/serial_number_util_unittest\.cc',
Daniel Chengddde13a2024-09-05 21:39:28[diff] [blame]2062 r'^components/history/core/browser/visit_annotations_database\.cc',
2063 r'^components/history/core/browser/visit_annotations_database_unittest\.cc',
2064 r'^components/os_crypt/sync/os_crypt_unittest\.cc',
2065 r'^components/password_manager/core/browser/credentials_cleaner_unittest\.cc',
2066 r'^content/browser/file_system_access/file_system_access_file_writer_impl_unittest\.cc',
2067 r'^net/cookies/parsed_cookie_unittest\.cc',
2068 r'^third_party/blink/renderer/modules/webcodecs/test_helpers\.cc',
2069 r'^third_party/blink/renderer/modules/websockets/websocket_channel_impl_test\.cc',
2070),
Erik Chenba8b0cd32024-10-01 08:36:36[diff] [blame]2071),
2072BanRule(
2073 pattern='BUILDFLAG(GOOGLE_CHROME_BRANDING)',
2074 explanation=
2075('Code gated by GOOGLE_CHROME_BRANDING is effectively untested. This '
2076'is typically wrong. Valid use cases are glue for private modules '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2077'shipped alongside Chrome, and installation-related logic.',),
Erik Chenba8b0cd32024-10-01 08:36:36[diff] [blame]2078 treat_as_error=False,
2079),
2080BanRule(
2081 pattern='defined(OFFICIAL_BUILD)',
2082 explanation=
2083('Code gated by OFFICIAL_BUILD is effectively untested. This '
2084'is typically wrong. One valid use case is low-level code that '
2085'handles subtleties related to high-levels of optimizations that come '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2086'with OFFICIAL_BUILD.',),
Erik Chenba8b0cd32024-10-01 08:36:36[diff] [blame]2087 treat_as_error=False,
2088),
Erik Chen95b9c782024-11-08 03:26:27[diff] [blame]2089BanRule(
2090 pattern='WebContentsDestroyed',
2091 explanation=
2092('Do not use this method. It is invoked half-way through the '
2093'destructor of WebContentsImpl and using it often results in crashes '
2094'or surprising behavior. Conceptually, this is only necessary by '
2095'objects that depend on, but outlive the WebContents. These objects '
2096'should instead coordinate with the owner of the WebContents which is '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2097'responsible for destroying the WebContents.',),
Erik Chen95b9c782024-11-08 03:26:27[diff] [blame]2098 treat_as_error=False,
2099),
Maksim Sisovc98fdfa2024-11-16 20:12:27[diff] [blame]2100BanRule(
Georg Neisa7f94e62025-02-28 07:01:48[diff] [blame]2101 pattern='IS_CHROMEOS_ASH',
Maksim Sisovc98fdfa2024-11-16 20:12:27[diff] [blame]2102 explanation=
Georg Neisa7f94e62025-02-28 07:01:48[diff] [blame]2103('IS_CHROMEOS_ASH is deprecated. Please use the equivalent IS_CHROMEOS '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2104'instead (Lacros is gone).',),
Maksim Sisovc98fdfa2024-11-16 20:12:27[diff] [blame]2105 treat_as_error=False,
2106),
Erik Chen1396bbe2025-01-27 23:39:36[diff] [blame]2107BanRule(
2108 pattern=(r'namespace {'),
2109 explanation=
2110('Anonymous namespaces are disallowed in C++ header files. See '
2111'https://google.github.io/styleguide/cppguide.html#Internal_Linkage '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2112' for details.',),
Erik Chen1396bbe2025-01-27 23:39:36[diff] [blame]2113 treat_as_error=False,
2114 excluded_paths=[
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2115 _THIRD_PARTY_EXCEPT_BLINK,# Don't warn in third_party folders.
2116 r'^(?!.*\.h$).*$',# Exclude all files except those that end in .h
Erik Chen1396bbe2025-01-27 23:39:36[diff] [blame]2117],
2118),
Keren Zhuf06d757d2025-03-04 05:32:36[diff] [blame]2119BanRule(
2120 pattern=('AddChildViewRaw'),
2121 explanation=(
2122'Do not use AddChildViewRaw. It is prone to memory leaks and '
2123'use-after-free bugs. Instead, use AddChildView(std::unique_ptr). '
2124'See https://crbug.com/40485510 for more details.',),
2125 treat_as_error=False,
2126),
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]2127BanRule(
2128 pattern=(r'IS_DESKTOP_ANDROID'),
2129 explanation=(
Eric Lokc26a46662025-05-02 01:04:03[diff] [blame]2130'Do not add new uses of IS_DESKTOP_ANDROID build flag until you '
2131'have the approval of tedchoc@ or twellington@. '
2132'Background: it is highly important to reduce the divergence of '
2133'features across platforms. '
2134'Allowances may be granted to only the directories below: '
2135'[build/, chrome/, components/, extensions/, infra/, tools/] ',
2136'Note: in particular we need to avoid components shared with '
2137'WebView.',
2138),
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]2139 treat_as_error=False,
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2140 surface_as_gerrit_lint=True,
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]2141),
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]2142)
2143
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2144_DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING=(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2145'Used a predicate related to signin::ConsentLevel::kSync which will always '
2146'return false in the future (crbug.com/40066949). Prefer using a predicate '
2147'that also supports signin::ConsentLevel::kSignin when appropriate. It is '
2148'safe to ignore this warning if you are just moving an existing call, or if '
2149'you want special handling for users in the legacy state. In doubt, reach '
2150'out to //components/sync/OWNERS.',)
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2151
2152# C++ functions related to signin::ConsentLevel::kSync which are deprecated.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2153_DEPRECATED_SYNC_CONSENT_CPP_FUNCTIONS:Sequence[BanRule]=(
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2154BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2155'HasSyncConsent',
2156 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2157False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2158),
2159BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2160'CanSyncFeatureStart',
2161 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2162False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2163),
2164BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2165'IsSyncFeatureEnabled',
2166 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2167False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2168),
2169BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2170'IsSyncFeatureActive',
2171 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2172False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2173),
2174)
2175
2176# Java functions related to signin::ConsentLevel::kSync which are deprecated.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2177_DEPRECATED_SYNC_CONSENT_JAVA_FUNCTIONS:Sequence[BanRule]=(
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2178BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2179'hasSyncConsent',
2180 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2181False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2182),
2183BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2184'canSyncFeatureStart',
2185 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2186False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2187),
2188BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2189'isSyncFeatureEnabled',
2190 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2191False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2192),
2193BanRule(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2194'isSyncFeatureActive',
2195 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2196False,
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2197),
2198)
2199
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]2200_BANNED_MOJOM_PATTERNS:Sequence[BanRule]=(
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]2201BanRule(
2202'handle<shared_buffer>',
2203(
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]2204'Please use one of the more specific shared memory types instead:',
2205' mojo_base.mojom.ReadOnlySharedMemoryRegion',
2206' mojo_base.mojom.WritableSharedMemoryRegion',
2207' mojo_base.mojom.UnsafeSharedMemoryRegion',
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]2208),
2209True,
2210),
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]2211BanRule(
2212'string extension_id',
2213(
2214'Please use the extensions::mojom::ExtensionId struct when '
2215'passing extensions::ExtensionIds as mojom messages in order to ',
2216'provide message validation.',
2217),
2218True,
2219# Only apply this to (mojom) files in a subdirectory of extensions.
2220 excluded_paths=(r'^((?!extensions/).)*$',),
2221),
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]2222)
2223
mlamouria82272622014-09-16 18:45:04[diff] [blame]2224_IPC_ENUM_TRAITS_DEPRECATED=(
2225'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:50[diff] [blame]2226'See http://www.chromium.org/Home/chromium-security/education/'
2227'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:04[diff] [blame]2228
Stephen Martinis97a394142018-06-07 23:06:05[diff] [blame]2229_LONG_PATH_ERROR=(
2230'Some files included in this CL have file names that are too long (> 200'
2231' characters). If committed, these files will cause issues on Windows. See'
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2232' https://crbug.com/612667 for more details.')
Stephen Martinis97a394142018-06-07 23:06:05[diff] [blame]2233
Shenghua Zhangbfaa38b82017-11-16 21:58:02[diff] [blame]2234_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS=[
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]2235 r".*/BuildHooksAndroidImpl\.java",
2236 r".*/LicenseContentProvider\.java",
2237 r".*/PlatformServiceBridgeImpl.java",
2238 r".*chrome/android/feed/dummy/.*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:02[diff] [blame]2239]
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]2240
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]2241# List of image extensions that are used as resources in chromium.
2242_IMAGE_EXTENSIONS=['.svg','.png','.webp']
2243
Sean Kau46e29bc2017-08-28 16:31:16[diff] [blame]2244# These paths contain test data and other known invalid JSON files.
Erik Staab2dd72b12020-04-16 15:03:40[diff] [blame]2245_KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS=[
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]2246 r'test/data/',
2247 r'testing/buildbot/',
2248 r'^components/policy/resources/policy_templates\.json$',
2249 r'^third_party/protobuf/',
Camillo Bruni1411a352023-05-24 12:39:03[diff] [blame]2250 r'^third_party/blink/perf_tests/speedometer.*/resources/todomvc/learn\.json',
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]2251 r'^third_party/blink/renderer/devtools/protocol\.json$',
2252 r'^third_party/blink/web_tests/external/wpt/',
2253 r'^tools/perf/',
2254 r'^tools/traceline/svgui/startup-release.json',
Daniel Cheng2d4c2d192022-07-01 01:38:31[diff] [blame]2255# vscode configuration files allow comments
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]2256 r'^tools/vscode/',
Sean Kau46e29bc2017-08-28 16:31:16[diff] [blame]2257]
2258
Andrew Grieveb773bad2020-06-05 18:00:38[diff] [blame]2259# These are not checked on the public chromium-presubmit trybot.
2260# Add files here that rely on .py files that exists only for target_os="android"
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2261# checkouts.
agrievef32bcc72016-04-04 14:57:40[diff] [blame]2262_ANDROID_SPECIFIC_PYDEPS_FILES=[
Andrew Grieveb773bad2020-06-05 18:00:38[diff] [blame]2263'chrome/android/features/create_stripped_java_factory.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:38[diff] [blame]2264]
2265
Andrew Grieveb773bad2020-06-05 18:00:38[diff] [blame]2266_GENERIC_PYDEPS_FILES=[
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2267'android_webview/tools/run_cts.pydeps',
Andrew Grieve4c4cede2020-11-20 22:09:36[diff] [blame]2268'build/android/apk_operations.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2269'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2270'build/android/gyp/aar.pydeps',
2271'build/android/gyp/aidl.pydeps',
2272'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:38[diff] [blame]2273'build/android/gyp/assert_static_initializers.pydeps',
Mohamed Heikal133e1f22023-04-18 20:04:37[diff] [blame]2274'build/android/gyp/binary_baseline_profile.pydeps',
Robbie McElrath360e54d2020-11-12 20:38:02[diff] [blame]2275'build/android/gyp/bytecode_rewriter.pydeps',
Mohamed Heikal6305bcc2021-03-15 15:34:22[diff] [blame]2276'build/android/gyp/check_flag_expectations.pydeps',
Andrew Grieveacac4242024-12-20 19:39:42[diff] [blame]2277'build/android/gyp/check_for_missing_direct_deps.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:11[diff] [blame]2278'build/android/gyp/compile_java.pydeps',
Peter Weneaa963f2023-01-20 19:40:30[diff] [blame]2279'build/android/gyp/compile_kt.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2280'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2281'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2282'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:11[diff] [blame]2283'build/android/gyp/create_app_bundle.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2284'build/android/gyp/create_app_bundle_apks.pydeps',
2285'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2286'build/android/gyp/create_java_binary_script.pydeps',
Mohamed Heikaladbe4e482020-07-09 19:25:12[diff] [blame]2287'build/android/gyp/create_r_java.pydeps',
Mohamed Heikal8cd763a52021-02-01 23:32:09[diff] [blame]2288'build/android/gyp/create_r_txt.pydeps',
Andrew Grieveb838d832019-02-11 16:55:22[diff] [blame]2289'build/android/gyp/create_size_info_files.pydeps',
Andrew Grieve2d972e5f2025-01-28 18:28:14[diff] [blame]2290'build/android/gyp/create_stub_manifest.pydeps',
Peter Wene6e017e2022-07-27 21:40:40[diff] [blame]2291'build/android/gyp/create_test_apk_wrapper_script.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:00[diff] [blame]2292'build/android/gyp/create_ui_locale_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2293'build/android/gyp/dex.pydeps',
2294'build/android/gyp/dist_aar.pydeps',
Andrew Grieve651ddb32025-01-23 03:27:34[diff] [blame]2295'build/android/gyp/errorprone.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2296'build/android/gyp/filter_zip.pydeps',
Mohamed Heikal21e1994b2021-11-12 21:37:21[diff] [blame]2297'build/android/gyp/flatc_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2298'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:36[diff] [blame]2299'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2300'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:58[diff] [blame]2301'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2302'build/android/gyp/java_cpp_enum.pydeps',
Nate Fischerac07b2622020-10-01 20:20:14[diff] [blame]2303'build/android/gyp/java_cpp_features.pydeps',
Ian Vollickb99472e2019-03-07 21:35:26[diff] [blame]2304'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve09457912021-04-27 15:22:47[diff] [blame]2305'build/android/gyp/java_google_api_keys.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2306'build/android/gyp/jinja_template.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2307'build/android/gyp/lint.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2308'build/android/gyp/merge_manifest.pydeps',
Bruce Dawson853b739e62022-05-03 23:03:10[diff] [blame]2309'build/android/gyp/optimize_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2310'build/android/gyp/prepare_resources.pydeps',
Mohamed Heikalf85138b2020-10-06 15:43:22[diff] [blame]2311'build/android/gyp/process_native_prebuilt.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2312'build/android/gyp/proguard.pydeps',
Mohamed Heikaldd52b452024-09-10 17:10:50[diff] [blame]2313'build/android/gyp/rename_java_classes.pydeps',
Andrew Grievee3a775ab2022-05-16 15:59:22[diff] [blame]2314'build/android/gyp/system_image_apks.pydeps',
Bruce Dawson853b739e62022-05-03 23:03:10[diff] [blame]2315'build/android/gyp/trace_event_bytecode_rewriter.pydeps',
Andrew Grieve170b9782025-02-03 15:54:53[diff] [blame]2316'build/android/gyp/tracereferences.pydeps',
Peter Wen578730b2020-03-19 19:55:46[diff] [blame]2317'build/android/gyp/turbine.pydeps',
Mohamed Heikal246710c2021-06-14 15:34:30[diff] [blame]2318'build/android/gyp/unused_resources.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:24[diff] [blame]2319'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2320'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:46[diff] [blame]2321'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:56[diff] [blame]2322'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2323'build/android/incremental_install/generate_android_manifest.pydeps',
2324'build/android/incremental_install/write_installer_json.pydeps',
Stephanie Kim392913b452022-06-15 17:25:32[diff] [blame]2325'build/android/pylib/results/presentation/test_results_presentation.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2326'build/android/resource_sizes.pydeps',
2327'build/android/test_runner.pydeps',
2328'build/android/test_wrapper/logdog_wrapper.pydeps',
zijiehe-google-com356980f2025-05-08 20:58:15[diff] [blame]2329'build/fuchsia/test/component_storage_test.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:36[diff] [blame]2330'build/protoc_java.pydeps',
Peter Kotwicz64667b02020-10-18 06:43:32[diff] [blame]2331'chrome/android/monochrome/scripts/monochrome_python_tests.pydeps',
Peter Wenefb56c72020-06-04 15:12:27[diff] [blame]2332'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
2333'chrome/test/chromedriver/test/run_py_tests.pydeps',
Bailey Myers-Morganbd122132025-03-26 23:09:16[diff] [blame]2334'chrome/test/media_router/performance/performance_test.pydeps',
Junbo Kedcd3a452021-03-19 17:55:04[diff] [blame]2335'chromecast/resource_sizes/chromecast_resource_sizes.pydeps',
Mohannad Farrag19102742023-12-01 01:16:30[diff] [blame]2336'components/cronet/tools/check_combined_proguard_file.pydeps',
2337'components/cronet/tools/generate_proguard_file.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:00[diff] [blame]2338'components/cronet/tools/jar_src.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:38[diff] [blame]2339'components/module_installer/android/module_desc_java.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:00[diff] [blame]2340'content/public/android/generate_child_service.pydeps',
Hzj_jie77bdb802024-07-22 18:14:51[diff] [blame]2341'fuchsia_web/av_testing/av_sync_tests.pydeps',
Peter Kotwicz3c339f32020-10-19 19:59:18[diff] [blame]2342'testing/scripts/run_isolated_script_test.pydeps',
Stephanie Kimc94072c2022-03-22 22:31:41[diff] [blame]2343'testing/merge_scripts/standard_isolated_script_merge.pydeps',
2344'testing/merge_scripts/standard_gtest_merge.pydeps',
2345'testing/merge_scripts/code_coverage/merge_results.pydeps',
2346'testing/merge_scripts/code_coverage/merge_steps.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:04[diff] [blame]2347'third_party/android_platform/development/scripts/stack.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:42[diff] [blame]2348'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
Yuki Shiino38eeaad12022-08-11 06:40:25[diff] [blame]2349'third_party/blink/renderer/bindings/scripts/check_generated_file_list.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:42[diff] [blame]2350'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:13[diff] [blame]2351'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Yuki Shiinoea477d32023-08-21 06:24:34[diff] [blame]2352'third_party/blink/renderer/bindings/scripts/generate_event_interface_names.pydeps',
Canon Mukaif32f8f592021-04-23 18:56:50[diff] [blame]2353'third_party/blink/renderer/bindings/scripts/validate_web_idl.pydeps',
Stephanie Kimc94072c2022-03-22 22:31:41[diff] [blame]2354'third_party/blink/tools/blinkpy/web_tests/merge_results.pydeps',
2355'third_party/blink/tools/merge_web_test_results.pydeps',
John Budorickbc3571aa2019-04-25 02:20:06[diff] [blame]2356'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:22[diff] [blame]2357'tools/binary_size/supersize.pydeps',
Peter Wen2dcfa6e2025-03-04 22:42:52[diff] [blame]2358'tools/cygprofile/generate_orderfile.pydeps',
Ben Pastene028104a2022-08-10 19:17:45[diff] [blame]2359'tools/perf/process_perf_results.pydeps',
Peter Wence103e12024-10-09 19:23:51[diff] [blame]2360'tools/pgo/generate_profile.pydeps',
agrievef32bcc72016-04-04 14:57:40[diff] [blame]2361]
2362
2363_ALL_PYDEPS_FILES= _ANDROID_SPECIFIC_PYDEPS_FILES+ _GENERIC_PYDEPS_FILES
2364
Eric Boren6fd2b932018-01-25 15:05:08[diff] [blame]2365# Bypass the AUTHORS check for these accounts.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2366_KNOWN_ROBOTS= set()| set('%s@appspot.gserviceaccount.com'% sfor sin(
2367'findit-for-me','luci-bisection','predator-for-me-staging',
2368'predator-for-me'))| set(
2369'%s@developer.gserviceaccount.com'% s
2370for sin('3su6n15k.default',))| set(
2371'%s@chops-service-accounts.iam.gserviceaccount.com'% s
2372for sin('bling-autoroll-builder','v8-ci-autoroll-builder',
2373'wpt-autoroller','chrome-weblayer-builder',
2374'skylab-test-cros-roller','infra-try-recipes-tester',
2375'chrome-automated-expectation',
2376'chromium-automated-expectation','chrome-branch-day',
2377'chrome-cherry-picker','chromium-autosharder')
2378)| set(
2379'%s@skia-public.iam.gserviceaccount.com'% s
2380for sin('chromium-autoroll','chromium-release-autoroll'))| set(
2381'%s@skia-corp.google.com.iam.gserviceaccount.com'% s
2382for sin('chromium-internal-autoroll',)
2383)| set(
2384'%s@system.gserviceaccount.com'%
2385 sfor sin('chrome-screen-ai-releaser','crash-eng','crash')
2386)| set(
2387'%s@owners-cleanup-prod.google.com.iam.gserviceaccount.com'% s
2388for sin('swarming-tasks',))| set(
2389'%s@fuchsia-infra.iam.gserviceaccount.com'% s
2390for sin('global-integration-try-builder',
Rachael Newitte5664ef92025-05-08 14:00:23[diff] [blame]2391'global-integration-ci-builder')
2392)| set('%s@prod.google.com'% sfor sin(
2393'chops-security-borg',
2394'chops-security-cronjobs-cpesuggest'))| set(
2395'%s@chromeos-release-bot.iam.gserviceaccount.com'% s
Joey Scarrf55d5c42025-07-07 22:03:06[diff] [blame]2396for sin('chromeos-ci-release',))| set(
2397'%s@chromeos-bot.iam.gserviceaccount.com'% s
2398for sin('chromeos-ci-prod',))
Eric Boren6fd2b932018-01-25 15:05:08[diff] [blame]2399
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2400_INVALID_GRD_FILE_LINE=[(r'<file lang=.* path=.*',
2401'Path should come before lang in GRD files.')]
2402
Eric Boren6fd2b932018-01-25 15:05:08[diff] [blame]2403
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2404def_IsCPlusPlusFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2405"""Returns True if this file contains C++-like code (and not Python,
2406 Go, Java, MarkDown, ...)"""
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2407
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2408 ext= input_api.os_path.splitext(file_path)[1]
2409# This list is compatible with CppChecker.IsCppFile but we should
2410# consider adding ".c" to it. If we do that we can use this function
2411# at more places in the code.
2412return extin(
2413'.h',
2414'.cc',
2415'.cpp',
2416'.m',
2417'.mm',
2418)
2419
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2420
2421def_IsCPlusPlusHeaderFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2422return input_api.os_path.splitext(file_path)[1]==".h"
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2423
2424
2425def_IsJavaFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2426return input_api.os_path.splitext(file_path)[1]==".java"
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2427
2428
2429def_IsProtoFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2430return input_api.os_path.splitext(file_path)[1]==".proto"
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2431
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]2432
Erik Staabc734cd7a2021-11-23 03:11:52[diff] [blame]2433def_IsXmlOrGrdFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2434 ext= input_api.os_path.splitext(file_path)[1]
2435return extin('.grd','.xml')
Erik Staabc734cd7a2021-11-23 03:11:52[diff] [blame]2436
2437
Sven Zheng76a79ea2022-12-21 21:25:24[diff] [blame]2438def_IsMojomFile(input_api, file_path):
2439return input_api.os_path.splitext(file_path)[1]==".mojom"
2440
2441
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]2442defCheckNoUpstreamDepsOnClank(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2443"""Prevent additions of dependencies from the upstream repo on //clank."""
2444# clank can depend on clank
2445if input_api.change.RepositoryRoot().endswith('clank'):
2446return[]
2447 build_file_patterns=[
2448 r'(.+/)?BUILD\.gn',
2449 r'.+\.gni',
2450]
2451 excluded_files=[r'build[/\\]config[/\\]android[/\\]config\.gni']
2452 bad_pattern= input_api.re.compile(r'^[^#]*//clank')
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]2453
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2454 error_message='Disallowed import on //clank in an upstream build file:'
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]2455
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2456defFilterFile(affected_file):
2457return input_api.FilterSourceFile(affected_file,
2458 files_to_check=build_file_patterns,
2459 files_to_skip=excluded_files)
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]2460
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2461 problems=[]
2462for fin input_api.AffectedSourceFiles(FilterFile):
2463 local_path= f.LocalPath()
2464for line_number, linein f.ChangedContents():
2465if(bad_pattern.search(line)):
2466 problems.append('%s:%d\n %s'%
2467(local_path, line_number, line.strip()))
2468if problems:
2469return[output_api.PresubmitPromptOrNotify(error_message, problems)]
2470else:
2471return[]
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]2472
2473
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2474defCheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2475"""Attempts to prevent use of functions intended only for testing in
2476 non-testing code. For now this is just a best-effort implementation
2477 that ignores header files and may have some false positives. A
2478 better implementation would probably need a proper C++ parser.
2479 """
2480# We only scan .cc files and the like, as the declaration of
2481# for-testing functions in header files are hard to distinguish from
2482# calls to such functions without a proper C++ parser.
2483 file_inclusion_pattern=[r'.+%s'% _IMPLEMENTATION_EXTENSIONS]
joi@chromium.org55459852011-08-10 15:17:19[diff] [blame]2484
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2485 base_function_pattern= r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
2486 inclusion_pattern= input_api.re.compile(r'(%s)\s*\('%
2487 base_function_pattern)
2488 comment_pattern= input_api.re.compile(r'//.*(%s)'% base_function_pattern)
2489 allowlist_pattern= input_api.re.compile(r'// IN-TEST$')
2490 exclusion_pattern= input_api.re.compile(
2491 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{'%
2492(base_function_pattern, base_function_pattern))
2493# Avoid a false positive in this case, where the method name, the ::, and
2494# the closing { are all on different lines due to line wrapping.
2495# HelperClassForTesting::
2496# HelperClassForTesting(
2497# args)
2498# : member(0) {}
2499 method_defn_pattern= input_api.re.compile(r'[A-Za-z0-9_]+::$')
joi@chromium.org55459852011-08-10 15:17:19[diff] [blame]2500
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2501defFilterFile(affected_file):
2502 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
2503 input_api.DEFAULT_FILES_TO_SKIP)
2504return input_api.FilterSourceFile(
2505 affected_file,
2506 files_to_check=file_inclusion_pattern,
2507 files_to_skip=files_to_skip)
joi@chromium.org55459852011-08-10 15:17:19[diff] [blame]2508
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2509 problems=[]
2510for fin input_api.AffectedSourceFiles(FilterFile):
2511 local_path= f.LocalPath()
2512 in_method_defn=False
2513for line_number, linein f.ChangedContents():
2514if(inclusion_pattern.search(line)
2515andnot comment_pattern.search(line)
2516andnot exclusion_pattern.search(line)
2517andnot allowlist_pattern.search(line)
2518andnot in_method_defn):
2519 problems.append('%s:%d\n %s'%
2520(local_path, line_number, line.strip()))
2521 in_method_defn= method_defn_pattern.search(line)
joi@chromium.org55459852011-08-10 15:17:19[diff] [blame]2522
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2523if problems:
2524return[
2525 output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)
2526]
2527else:
2528return[]
joi@chromium.org55459852011-08-10 15:17:19[diff] [blame]2529
2530
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2531defCheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2532"""This is a simplified version of
2533 CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
2534 """
2535 javadoc_start_re= input_api.re.compile(r'^\s*/\*\*')
2536 javadoc_end_re= input_api.re.compile(r'^\s*\*/')
2537 name_pattern= r'ForTest(s|ing)?'
2538# Describes an occurrence of "ForTest*" inside a // comment.
2539 comment_re= input_api.re.compile(r'//.*%s'% name_pattern)
2540# Describes @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
2541 annotation_re= input_api.re.compile(r'@VisibleForTesting\(')
2542# Catch calls.
2543 inclusion_re= input_api.re.compile(r'(%s)\s*\('% name_pattern)
2544# Ignore definitions. (Comments are ignored separately.)
2545 exclusion_re= input_api.re.compile(r'(%s)[^;]+\{'% name_pattern)
Andrew Grieve40f451d2023-07-06 19:46:51[diff] [blame]2546 allowlist_re= input_api.re.compile(r'// IN-TEST$')
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]2547
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2548 problems=[]
2549 sources=lambda x: input_api.FilterSourceFile(
2550 x,
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2551 files_to_skip=(
2552('(?i).*test', r'.*\/junit\/')+ input_api.DEFAULT_FILES_TO_SKIP),
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2553 files_to_check=[r'.*\.java$'])
2554for fin input_api.AffectedFiles(include_deletes=False,
2555 file_filter=sources):
2556 local_path= f.LocalPath()
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]2557 is_inside_javadoc=False
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2558for line_number, linein f.ChangedContents():
2559if is_inside_javadocand javadoc_end_re.search(line):
2560 is_inside_javadoc=False
2561ifnot is_inside_javadocand javadoc_start_re.search(line):
2562 is_inside_javadoc=True
2563if is_inside_javadoc:
2564continue
2565if(inclusion_re.search(line)andnot comment_re.search(line)
2566andnot annotation_re.search(line)
Andrew Grieve40f451d2023-07-06 19:46:51[diff] [blame]2567andnot allowlist_re.search(line)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2568andnot exclusion_re.search(line)):
2569 problems.append('%s:%d\n %s'%
2570(local_path, line_number, line.strip()))
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]2571
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2572if problems:
2573return[
2574 output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)
2575]
2576else:
2577return[]
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]2578
2579
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2580defCheckNoIOStreamInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2581"""Checks to make sure no .h files include <iostream>."""
2582 files=[]
2583 pattern= input_api.re.compile(r'^#include\s*<iostream>',
2584 input_api.re.MULTILINE)
2585for fin input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2586ifnot f.LocalPath().endswith('.h'):
2587continue
2588 contents= input_api.ReadFile(f)
2589if pattern.search(contents):
2590 files.append(f)
thakis@chromium.org10689ca2011-09-02 02:31:54[diff] [blame]2591
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2592if len(files):
2593return[
2594 output_api.PresubmitError(
2595'Do not #include <iostream> in header files, since it inserts static '
2596'initialization into every file including the header. Instead, '
2597'#include <ostream>. See http://crbug.com/94794', files)
2598]
2599return[]
2600
thakis@chromium.org10689ca2011-09-02 02:31:54[diff] [blame]2601
Aleksey Khoroshilov9b28c032022-06-03 16:35:32[diff] [blame]2602defCheckNoStrCatRedefines(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2603"""Checks no windows headers with StrCat redefined are included directly."""
2604 files=[]
Aleksey Khoroshilov9b28c032022-06-03 16:35:32[diff] [blame]2605 files_to_check=(r'.+%s'% _HEADER_EXTENSIONS,
2606 r'.+%s'% _IMPLEMENTATION_EXTENSIONS)
2607 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP+
2608 _NON_BASE_DEPENDENT_PATHS)
2609 sources_filter=lambda f: input_api.FilterSourceFile(
2610 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
2611
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2612 pattern_deny= input_api.re.compile(
2613 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
2614 input_api.re.MULTILINE)
2615 pattern_allow= input_api.re.compile(
2616 r'^#include\s"base/win/windows_defines.inc"', input_api.re.MULTILINE)
Aleksey Khoroshilov9b28c032022-06-03 16:35:32[diff] [blame]2617for fin input_api.AffectedSourceFiles(sources_filter):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2618 contents= input_api.ReadFile(f)
2619if pattern_deny.search(
2620 contents)andnot pattern_allow.search(contents):
2621 files.append(f.LocalPath())
Danil Chapovalov3518f362018-08-11 16:13:43[diff] [blame]2622
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2623if len(files):
2624return[
2625 output_api.PresubmitError(
2626'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
2627'directly since they pollute code with StrCat macro. Instead, '
2628'include matching header from base/win. See http://crbug.com/856536',
2629 files)
2630]
2631return[]
Danil Chapovalov3518f362018-08-11 16:13:43[diff] [blame]2632
thakis@chromium.org10689ca2011-09-02 02:31:54[diff] [blame]2633
Andrew Williamsc9f69b482023-07-10 16:07:36[diff] [blame]2634def_CheckNoUNIT_TESTInSourceFiles(input_api, f):
2635 problems=[]
2636
2637 unit_test_macro= input_api.re.compile(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2638 r'^\s*#.*(?:ifn?def\s+UNIT_TEST|defined\s*\(?\s*UNIT_TEST\s*\)?)(?:$|\s+)'
2639)
Andrew Williamsc9f69b482023-07-10 16:07:36[diff] [blame]2640for line_num, linein f.ChangedContents():
2641if unit_test_macro.match(line):
2642 problems.append(' %s:%d'%(f.LocalPath(), line_num))
2643
2644return problems
2645
2646
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2647defCheckNoUNIT_TESTInSourceFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2648"""Checks to make sure no source files use UNIT_TEST."""
2649 problems=[]
2650for fin input_api.AffectedFiles():
2651if(not f.LocalPath().endswith(('.cc','.mm'))):
2652continue
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2653 problems.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, f))
jam@chromium.org72df4e782012-06-21 16:28:18[diff] [blame]2654
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2655ifnot problems:
2656return[]
2657return[
2658 output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n'+
2659'\n'.join(problems))
2660]
2661
jam@chromium.org72df4e782012-06-21 16:28:18[diff] [blame]2662
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2663defCheckNoDISABLETypoInTests(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2664"""Checks to prevent attempts to disable tests with DISABLE_ prefix.
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2665
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2666 This test warns if somebody tries to disable a test with the DISABLE_ prefix
2667 instead of DISABLED_. To filter false positives, reports are only generated
2668 if a corresponding MAYBE_ line exists.
2669 """
2670 problems=[]
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2671
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2672# The following two patterns are looked for in tandem - is a test labeled
2673# as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
2674 maybe_pattern= input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
2675 disable_pattern= input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2676
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2677# This is for the case that a test is disabled on all platforms.
2678 full_disable_pattern= input_api.re.compile(
2679 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
2680 input_api.re.MULTILINE)
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2681
Arthur Sonzognic66e9c82024-04-23 07:53:04[diff] [blame]2682for fin input_api.AffectedFiles(include_deletes=False):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2683ifnot'test'in f.LocalPath()ornot f.LocalPath().endswith('.cc'):
2684continue
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2685
Arthur Sonzognic66e9c82024-04-23 07:53:04[diff] [blame]2686# Search for MAYBE_, DISABLE_ pairs.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2687 disable_lines={}# Maps of test name to line number.
2688 maybe_lines={}
2689for line_num, linein f.ChangedContents():
2690 disable_match= disable_pattern.search(line)
2691if disable_match:
2692 disable_lines[disable_match.group(1)]= line_num
2693 maybe_match= maybe_pattern.search(line)
2694if maybe_match:
2695 maybe_lines[maybe_match.group(1)]= line_num
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2696
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2697# Search for DISABLE_ occurrences within a TEST() macro.
2698 disable_tests= set(disable_lines.keys())
2699 maybe_tests= set(maybe_lines.keys())
2700for testin disable_tests.intersection(maybe_tests):
2701 problems.append(' %s:%d'%(f.LocalPath(), disable_lines[test]))
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2702
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2703 contents= input_api.ReadFile(f)
2704 full_disable_match= full_disable_pattern.search(contents)
2705if full_disable_match:
2706 problems.append(' %s'% f.LocalPath())
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2707
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2708ifnot problems:
2709return[]
2710return[
2711 output_api.PresubmitPromptWarning(
2712'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n'+
2713'\n'.join(problems))
2714]
2715
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]2716
Nina Satragnof7660532021-09-20 18:03:35[diff] [blame]2717defCheckForgettingMAYBEInTests(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2718"""Checks to make sure tests disabled conditionally are not missing a
2719 corresponding MAYBE_ prefix.
2720 """
2721# Expect at least a lowercase character in the test name. This helps rule out
2722# false positives with macros wrapping the actual tests name.
2723 define_maybe_pattern= input_api.re.compile(
2724 r'^\#define MAYBE_(?P<test_name>\w*[a-z]\w*)')
Bruce Dawsonffc55292022-04-20 04:18:19[diff] [blame]2725# The test_maybe_pattern needs to handle all of these forms. The standard:
2726# IN_PROC_TEST_F(SyncTest, MAYBE_Start) {
2727# With a wrapper macro around the test name:
2728# IN_PROC_TEST_F(SyncTest, E2E_ENABLED(MAYBE_Start)) {
2729# And the odd-ball NACL_BROWSER_TEST_f format:
2730# NACL_BROWSER_TEST_F(NaClBrowserTest, SimpleLoad, {
2731# The optional E2E_ENABLED-style is handled with (\w*\()?
2732# The NACL_BROWSER_TEST_F pattern is handled by allowing a trailing comma or
2733# trailing ')'.
2734 test_maybe_pattern=(
2735 r'^\s*\w*TEST[^(]*\(\s*\w+,\s*(\w*\()?MAYBE_{test_name}[\),]')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2736 suite_maybe_pattern= r'^\s*\w*TEST[^(]*\(\s*MAYBE_{test_name}[\),]'
2737 warnings=[]
Nina Satragnof7660532021-09-20 18:03:35[diff] [blame]2738
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2739# Read the entire files. We can't just read the affected lines, forgetting to
2740# add MAYBE_ on a change would not show up otherwise.
Arthur Sonzognic66e9c82024-04-23 07:53:04[diff] [blame]2741for fin input_api.AffectedFiles(include_deletes=False):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2742ifnot'test'in f.LocalPath()ornot f.LocalPath().endswith('.cc'):
2743continue
2744 contents= input_api.ReadFile(f)
2745 lines= contents.splitlines(True)
2746 current_position=0
2747 warning_test_names= set()
2748for line_num, linein enumerate(lines, start=1):
2749 current_position+= len(line)
2750 maybe_match= define_maybe_pattern.search(line)
2751if maybe_match:
2752 test_name= maybe_match.group('test_name')
2753# Do not warn twice for the same test.
2754if(test_namein warning_test_names):
2755continue
2756 warning_test_names.add(test_name)
Nina Satragnof7660532021-09-20 18:03:35[diff] [blame]2757
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2758# Attempt to find the corresponding MAYBE_ test or suite, starting from
2759# the current position.
2760 test_match= input_api.re.compile(
2761 test_maybe_pattern.format(test_name=test_name),
2762 input_api.re.MULTILINE).search(contents, current_position)
2763 suite_match= input_api.re.compile(
2764 suite_maybe_pattern.format(test_name=test_name),
2765 input_api.re.MULTILINE).search(contents, current_position)
2766ifnot test_matchandnot suite_match:
2767 warnings.append(
2768 output_api.PresubmitPromptWarning(
2769'%s:%d found MAYBE_ defined without corresponding test %s'
2770%(f.LocalPath(), line_num, test_name)))
2771return warnings
2772
jam@chromium.org72df4e782012-06-21 16:28:18[diff] [blame]2773
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2774defCheckDCHECK_IS_ONHasBraces(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2775"""Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
2776 errors=[]
Kalvin Lee4a3b79de2022-05-26 16:00:16[diff] [blame]2777 pattern= input_api.re.compile(r'\bDCHECK_IS_ON\b(?!\(\))',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2778 input_api.re.MULTILINE)
2779for fin input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2780if(not f.LocalPath().endswith(('.cc','.mm','.h'))):
2781continue
2782for lnum, linein f.ChangedContents():
2783if input_api.re.search(pattern, line):
2784 errors.append(
2785 output_api.PresubmitError((
2786'%s:%d: Use of DCHECK_IS_ON() must be written as "#if '
2787+'DCHECK_IS_ON()", not forgetting the parentheses.')%
2788(f.LocalPath(), lnum)))
2789return errors
danakj61c1aa22015-10-26 19:55:52[diff] [blame]2790
2791
Weilun Shia487fad2020-10-28 00:10:34[diff] [blame]2792# TODO(crbug/1138055): Reimplement CheckUmaHistogramChangesOnUpload check in a
2793# more reliable way. See
2794# https://chromium-review.googlesource.com/c/chromium/src/+/2500269
mcasasb7440c282015-02-04 14:52:19[diff] [blame]2795
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]2796
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2797defCheckFlakyTestUsage(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2798"""Check that FlakyTest annotation is our own instead of the android one"""
2799 pattern= input_api.re.compile(r'import android.test.FlakyTest;')
2800 files=[]
2801for fin input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2802if f.LocalPath().endswith('Test.java'):
2803if pattern.search(input_api.ReadFile(f)):
2804 files.append(f)
2805if len(files):
2806return[
2807 output_api.PresubmitError(
2808'Use org.chromium.base.test.util.FlakyTest instead of '
2809'android.test.FlakyTest', files)
2810]
2811return[]
mcasasb7440c282015-02-04 14:52:19[diff] [blame]2812
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]2813
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2814defCheckNoDEPSGIT(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2815"""Make sure .DEPS.git is never modified manually."""
2816if any(f.LocalPath().endswith('.DEPS.git')
2817for fin input_api.AffectedFiles()):
2818return[
2819 output_api.PresubmitError(
2820'Never commit changes to .DEPS.git. This file is maintained by an\n'
2821'automated system based on what\'s in DEPS and your changes will be\n'
2822'overwritten.\n'
2823'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
2824'get-the-code#Rolling_DEPS\n'
2825'for more information')
2826]
2827return[]
maruel@chromium.org2a8ac9c2011-10-19 17:20:44[diff] [blame]2828
2829
Sven Zheng76a79ea2022-12-21 21:25:24[diff] [blame]2830defCheckCrosApiNeedBrowserTest(input_api, output_api):
2831"""Check new crosapi should add browser test."""
2832 has_new_crosapi=False
2833 has_browser_test=False
2834for fin input_api.AffectedFiles():
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]2835 path= f.UnixLocalPath()
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2836if(path.startswith('chromeos/crosapi/mojom')
2837and_IsMojomFile(input_api, path)and f.Action()=='A'):
Sven Zheng76a79ea2022-12-21 21:25:24[diff] [blame]2838 has_new_crosapi=True
2839if path.endswith('browsertest.cc')or path.endswith('browser_test.cc'):
2840 has_browser_test=True
2841if has_new_crosapiandnot has_browser_test:
2842return[
2843 output_api.PresubmitPromptWarning(
2844'You are adding a new crosapi, but there is no file ends with '
2845'browsertest.cc file being added or modified. It is important '
2846'to add crosapi browser test coverage to avoid version '
2847' skew issues.\n'
2848'Check //docs/lacros/test_instructions.md for more information.'
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2849)
Sven Zheng76a79ea2022-12-21 21:25:24[diff] [blame]2850]
2851return[]
2852
2853
Mario Sanchez Prada2472cab2019-09-18 10:58:31[diff] [blame]2854def_GetMessageForMatchingType(input_api, affected_file, line_number, line,
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2855 ban_rule):
Allen Bauer84778682022-09-22 16:28:56[diff] [blame]2856"""Helper method for checking for banned constructs.
Mario Sanchez Prada2472cab2019-09-18 10:58:31[diff] [blame]2857
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2858 Returns an string composed of the name of the file, the line number where the
2859 match has been found and the additional text passed as |message| in case the
2860 target type name matches the text inside the line passed as parameter.
2861 """
2862 result=[]
Peng Huang9c5949a02020-06-11 19:20:54[diff] [blame]2863
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2864# Ignore comments about banned types.
2865if input_api.re.search(r"^ *//", line):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2866return result
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2867# A // nocheck comment will bypass this error.
2868if line.endswith(" nocheck"):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2869return result
2870
2871 matched=False
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2872if ban_rule.pattern[0:1]=='/':
2873 regex= ban_rule.pattern[1:]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2874if input_api.re.search(regex, line):
2875 matched=True
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2876elif ban_rule.patternin line:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2877 matched=True
2878
2879if matched:
2880 result.append(' %s:%d:'%(affected_file.LocalPath(), line_number))
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2881for linein ban_rule.explanation:
2882 result.append(' %s'% line)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2883
danakjd18e8892020-12-17 17:42:01[diff] [blame]2884return result
Mario Sanchez Prada2472cab2019-09-18 10:58:31[diff] [blame]2885
2886
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]2887defCheckNoBannedFunctions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2888"""Make sure that banned functions are not used."""
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2889 results=[]
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]2890
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2891defIsExcludedFile(affected_file, excluded_paths):
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2892ifnot excluded_paths:
2893returnFalse
2894
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]2895 local_path= affected_file.UnixLocalPath()
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2896for itemin excluded_paths:
2897if input_api.re.match(item, local_path):
2898returnTrue
2899returnFalse
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]2900
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2901defIsIosObjcFile(affected_file):
2902 local_path= affected_file.LocalPath()
2903if input_api.os_path.splitext(local_path)[-1]notin('.mm','.m',
2904'.h'):
2905returnFalse
2906 basename= input_api.os_path.basename(local_path)
2907if'ios'in basename.split('_'):
2908returnTrue
2909for sepin(input_api.os_path.sep, input_api.os_path.altsep):
2910if sepand'ios'in local_path.split(sep):
2911returnTrue
2912returnFalse
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]2913
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2914defCheckForMatch(affected_file, line_num: int, line: str,
2915 ban_rule:BanRule):
2916ifIsExcludedFile(affected_file, ban_rule.excluded_paths):
2917return
2918
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2919 message=_GetMessageForMatchingType(input_api, f, line_num, line,
2920 ban_rule)
2921if message:
2922 result_loc=[]
2923if ban_rule.surface_as_gerrit_lint:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2924 result_loc.append(
2925 output_api.PresubmitResultLocation(
2926 file_path=affected_file.LocalPath(),
2927 start_line=line_num,
2928 end_line=line_num,
2929))
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2930if ban_rule.treat_as_errorisnotNoneand ban_rule.treat_as_error:
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2931 results.append(
2932 output_api.PresubmitError('A banned function was used.\n'+
2933'\n'.join(message),
2934 locations=result_loc))
2935
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2936else:
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2937 results.append(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2938 output_api.PresubmitPromptWarning(
2939'A banned function was used.\n'+'\n'.join(message),
2940 locations=result_loc))
wnwenbdc444e2016-05-25 13:44:15[diff] [blame]2941
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2942 file_filter=lambda f: f.LocalPath().endswith(('.java'))
2943for fin input_api.AffectedFiles(file_filter=file_filter):
2944for line_num, linein f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2945for ban_rulein _BANNED_JAVA_FUNCTIONS:
2946CheckForMatch(f, line_num, line, ban_rule)
Eric Stevensona9a980972017-09-23 00:04:41[diff] [blame]2947
Clement Yan9b330cb2022-11-17 05:25:29[diff] [blame]2948 file_filter=lambda f: f.LocalPath().endswith(('.js','.ts'))
2949for fin input_api.AffectedFiles(file_filter=file_filter):
2950for line_num, linein f.ChangedContents():
2951for ban_rulein _BANNED_JAVASCRIPT_FUNCTIONS:
2952CheckForMatch(f, line_num, line, ban_rule)
2953
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2954 file_filter=lambda f: f.LocalPath().endswith(('.mm','.m','.h'))
2955for fin input_api.AffectedFiles(file_filter=file_filter):
2956for line_num, linein f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2957for ban_rulein _BANNED_OBJC_FUNCTIONS:
2958CheckForMatch(f, line_num, line, ban_rule)
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]2959
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2960for fin input_api.AffectedFiles(file_filter=IsIosObjcFile):
2961for line_num, linein f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2962for ban_rulein _BANNED_IOS_OBJC_FUNCTIONS:
2963CheckForMatch(f, line_num, line, ban_rule)
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]2964
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2965 egtest_filter=lambda f: f.LocalPath().endswith(('_egtest.mm'))
2966for fin input_api.AffectedFiles(file_filter=egtest_filter):
2967for line_num, linein f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2968for ban_rulein _BANNED_IOS_EGTEST_FUNCTIONS:
2969CheckForMatch(f, line_num, line, ban_rule)
Peter K. Lee6c03ccff2019-07-15 14:40:05[diff] [blame]2970
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]2971 file_filter=lambda f: f.LocalPath().endswith(('.cc','.mm','.h'))
2972for fin input_api.AffectedFiles(file_filter=file_filter):
2973for line_num, linein f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]2974for ban_rulein _BANNED_CPP_FUNCTIONS:
2975CheckForMatch(f, line_num, line, ban_rule)
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]2976
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2977# As of 05/2024, iOS fully migrated ConsentLevel::kSync to kSignin, and
2978# Android is in the process of preventing new users from entering kSync.
2979# So the warning is restricted to those platforms.
Riley Wong49be8a882025-02-27 00:38:23[diff] [blame]2980 ios_pattern= input_api.re.compile(r'(^|[\W_])ios[\W_]')
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]2981 file_filter=lambda f:(
2982 f.LocalPath().endswith(('.cc','.mm','.h'))and
2983('android'in f.LocalPath()or
2984# Simply checking for an 'ios' substring would
2985# catch unrelated cases, use a regex.
2986 ios_pattern.search(f.LocalPath())))
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]2987for fin input_api.AffectedFiles(file_filter=file_filter):
2988for line_num, linein f.ChangedContents():
2989for ban_rulein _DEPRECATED_SYNC_CONSENT_CPP_FUNCTIONS:
2990CheckForMatch(f, line_num, line, ban_rule)
2991
2992 file_filter=lambda f: f.LocalPath().endswith(('.java'))
2993for fin input_api.AffectedFiles(file_filter=file_filter):
2994for line_num, linein f.ChangedContents():
2995for ban_rulein _DEPRECATED_SYNC_CONSENT_JAVA_FUNCTIONS:
2996CheckForMatch(f, line_num, line, ban_rule)
2997
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]2998 file_filter=lambda f: f.LocalPath().endswith(('.mojom'))
2999for fin input_api.AffectedFiles(file_filter=file_filter):
3000for line_num, linein f.ChangedContents():
3001for ban_rulein _BANNED_MOJOM_PATTERNS:
3002CheckForMatch(f, line_num, line, ban_rule)
3003
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3004return results
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]3005
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]3006
Michael Thiessen44457642020-02-06 00:24:15[diff] [blame]3007def_CheckAndroidNoBannedImports(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3008"""Make sure that banned java imports are not used."""
3009 errors=[]
Michael Thiessen44457642020-02-06 00:24:15[diff] [blame]3010
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3011 file_filter=lambda f: f.LocalPath().endswith(('.java'))
3012for fin input_api.AffectedFiles(file_filter=file_filter):
3013for line_num, linein f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]3014for ban_rulein _BANNED_JAVA_IMPORTS:
3015# Consider merging this into the above function. There is no
3016# real difference anymore other than helping with a little
3017# bit of boilerplate text. Doing so means things like
3018# `treat_as_error` will also be uniformly handled.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3019 problems=_GetMessageForMatchingType(input_api, f, line_num,
Daniel Chenga44a1bcd2022-03-15 20:00:15[diff] [blame]3020 line, ban_rule)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3021if problems:
3022 errors.extend(problems)
3023 result=[]
3024if(errors):
3025 result.append(
3026 output_api.PresubmitError('Banned imports were used.\n'+
3027'\n'.join(errors)))
3028return result
Michael Thiessen44457642020-02-06 00:24:15[diff] [blame]3029
3030
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3031defCheckNoPragmaOnce(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3032"""Make sure that banned functions are not used."""
3033 files=[]
3034 pattern= input_api.re.compile(r'^#pragma\s+once', input_api.re.MULTILINE)
3035for fin input_api.AffectedSourceFiles(input_api.FilterSourceFile):
3036ifnot f.LocalPath().endswith('.h'):
3037continue
Bruce Dawson4c4c2922022-05-02 18:07:33[diff] [blame]3038if f.LocalPath().endswith('com_imported_mstscax.h'):
3039continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3040 contents= input_api.ReadFile(f)
3041if pattern.search(contents):
3042 files.append(f)
dcheng@chromium.org6c063c62012-07-11 19:11:06[diff] [blame]3043
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3044if files:
3045return[
3046 output_api.PresubmitError(
3047'Do not use #pragma once in header files.\n'
3048'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
3049 files)
3050]
3051return[]
dcheng@chromium.org6c063c62012-07-11 19:11:06[diff] [blame]3052
avi@chromium.org127f18ec2012-06-16 05:05:59[diff] [blame]3053
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3054defCheckNoTrinaryTrueFalse(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3055"""Checks to make sure we don't introduce use of foo ? true : false."""
3056 problems=[]
3057 pattern= input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
3058for fin input_api.AffectedFiles():
3059ifnot f.LocalPath().endswith(('.cc','.h','.inl','.m','.mm')):
3060continue
thestig@chromium.orge7479052012-09-19 00:26:12[diff] [blame]3061
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3062for line_num, linein f.ChangedContents():
3063if pattern.match(line):
3064 problems.append(' %s:%d'%(f.LocalPath(), line_num))
thestig@chromium.orge7479052012-09-19 00:26:12[diff] [blame]3065
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3066ifnot problems:
3067return[]
3068return[
3069 output_api.PresubmitPromptWarning(
3070'Please consider avoiding the "? true : false" pattern if possible.\n'
3071+'\n'.join(problems))
3072]
thestig@chromium.orge7479052012-09-19 00:26:12[diff] [blame]3073
3074
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3075defCheckUnwantedDependencies(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3076"""Runs checkdeps on #include and import statements added in this
3077 change. Breaking - rules is an error, breaking ! rules is a
3078 warning.
3079 """
3080# Return early if no relevant file types were modified.
3081for fin input_api.AffectedFiles():
3082 path= f.LocalPath()
3083if(_IsCPlusPlusFile(input_api, path)or_IsProtoFile(input_api, path)
3084or_IsJavaFile(input_api, path)):
3085break
joi@chromium.org55f9f382012-07-31 11:02:18[diff] [blame]3086else:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3087return[]
rhalavati08acd232017-04-03 07:23:28[diff] [blame]3088
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3089import sys
3090# We need to wait until we have an input_api object and use this
3091# roundabout construct to import checkdeps because this file is
3092# eval-ed and thus doesn't have __file__.
3093 original_sys_path= sys.path
3094try:
3095 sys.path= sys.path+[
3096 input_api.os_path.join(input_api.PresubmitLocalPath(),
3097'buildtools','checkdeps')
3098]
3099import checkdeps
3100from rulesimportRule
3101finally:
3102# Restore sys.path to what it was before.
3103 sys.path= original_sys_path
joi@chromium.org55f9f382012-07-31 11:02:18[diff] [blame]3104
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3105 added_includes=[]
3106 added_imports=[]
3107 added_java_imports=[]
3108for fin input_api.AffectedFiles():
3109if_IsCPlusPlusFile(input_api, f.LocalPath()):
3110 changed_lines=[linefor _, linein f.ChangedContents()]
3111 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
3112elif_IsProtoFile(input_api, f.LocalPath()):
3113 changed_lines=[linefor _, linein f.ChangedContents()]
3114 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
3115elif_IsJavaFile(input_api, f.LocalPath()):
3116 changed_lines=[linefor _, linein f.ChangedContents()]
3117 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:24[diff] [blame]3118
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3119 deps_checker= checkdeps.DepsChecker(input_api.PresubmitLocalPath())
3120
3121 error_descriptions=[]
3122 warning_descriptions=[]
3123 error_subjects= set()
3124 warning_subjects= set()
3125
3126for path, rule_type, rule_descriptionin deps_checker.CheckAddedCppIncludes(
3127 added_includes):
3128 path= input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
3129 description_with_path='%s\n %s'%(path, rule_description)
3130if rule_type==Rule.DISALLOW:
3131 error_descriptions.append(description_with_path)
3132 error_subjects.add("#includes")
3133else:
3134 warning_descriptions.append(description_with_path)
3135 warning_subjects.add("#includes")
3136
3137for path, rule_type, rule_descriptionin deps_checker.CheckAddedProtoImports(
3138 added_imports):
3139 path= input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
3140 description_with_path='%s\n %s'%(path, rule_description)
3141if rule_type==Rule.DISALLOW:
3142 error_descriptions.append(description_with_path)
3143 error_subjects.add("imports")
3144else:
3145 warning_descriptions.append(description_with_path)
3146 warning_subjects.add("imports")
3147
3148for path, rule_type, rule_descriptionin deps_checker.CheckAddedJavaImports(
3149 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
3150 path= input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
3151 description_with_path='%s\n %s'%(path, rule_description)
3152if rule_type==Rule.DISALLOW:
3153 error_descriptions.append(description_with_path)
3154 error_subjects.add("imports")
3155else:
3156 warning_descriptions.append(description_with_path)
3157 warning_subjects.add("imports")
3158
3159 results=[]
3160if error_descriptions:
3161 results.append(
3162 output_api.PresubmitError(
3163'You added one or more %s that violate checkdeps rules.'%
3164" and ".join(error_subjects), error_descriptions))
3165if warning_descriptions:
3166 results.append(
3167 output_api.PresubmitPromptOrNotify(
3168'You added one or more %s of files that are temporarily\n'
3169'allowed but being removed. Can you avoid introducing the\n'
3170'%s? See relevant DEPS file(s) for details and contacts.'%
3171(" and ".join(warning_subjects),"/".join(warning_subjects)),
3172 warning_descriptions))
3173return results
joi@chromium.org55f9f382012-07-31 11:02:18[diff] [blame]3174
3175
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3176defCheckFilePermissions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3177"""Check that all files have their permissions properly set."""
3178if input_api.platform=='win32':
3179return[]
3180 checkperms_tool= input_api.os_path.join(input_api.PresubmitLocalPath(),
3181'tools','checkperms',
3182'checkperms.py')
3183 args=[
Bruce Dawson8a43cf72022-05-13 17:10:32[diff] [blame]3184 input_api.python3_executable, checkperms_tool,'--root',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3185 input_api.change.RepositoryRoot()
3186]
3187with input_api.CreateTemporaryFile()as file_list:
3188for fin input_api.AffectedFiles():
3189# checkperms.py file/directory arguments must be relative to the
3190# repository.
3191 file_list.write((f.LocalPath()+'\n').encode('utf8'))
3192 file_list.close()
3193 args+=['--file-list', file_list.name]
3194try:
3195 input_api.subprocess.check_output(args)
3196return[]
3197except input_api.subprocess.CalledProcessErroras error:
3198return[
3199 output_api.PresubmitError('checkperms.py failed:',
3200 long_text=error.output.decode(
3201'utf-8','ignore'))
3202]
csharp@chromium.orgfbcafe5a2012-08-08 15:31:22[diff] [blame]3203
3204
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3205defCheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3206"""Makes sure we don't include ui/aura/window_property.h
3207 in header files.
3208 """
3209 pattern= input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
3210 errors=[]
3211for fin input_api.AffectedFiles():
3212ifnot f.LocalPath().endswith('.h'):
3213continue
3214for line_num, linein f.ChangedContents():
3215if pattern.match(line):
3216 errors.append(' %s:%d'%(f.LocalPath(), line_num))
oshima@chromium.orgc8278b32012-10-30 20:35:49[diff] [blame]3217
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3218 results=[]
3219if errors:
3220 results.append(
3221 output_api.PresubmitError(
3222'Header files should not include ui/aura/window_property.h',
3223 errors))
3224return results
oshima@chromium.orgc8278b32012-10-30 20:35:49[diff] [blame]3225
3226
Omer Katzcc77ea92021-04-26 10:23:28[diff] [blame]3227defCheckNoInternalHeapIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3228"""Makes sure we don't include any headers from
3229 third_party/blink/renderer/platform/heap/impl or
3230 third_party/blink/renderer/platform/heap/v8_wrapper from files outside of
3231 third_party/blink/renderer/platform/heap
3232 """
3233 impl_pattern= input_api.re.compile(
3234 r'^\s*#include\s*"third_party/blink/renderer/platform/heap/impl/.*"')
3235 v8_wrapper_pattern= input_api.re.compile(
3236 r'^\s*#include\s*"third_party/blink/renderer/platform/heap/v8_wrapper/.*"'
3237)
3238 file_filter=lambda f:not input_api.re.match(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3239 r"^third_party/blink/renderer/platform/heap/.*", f.UnixLocalPath())
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3240 errors=[]
Omer Katzcc77ea92021-04-26 10:23:28[diff] [blame]3241
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3242for fin input_api.AffectedFiles(file_filter=file_filter):
3243for line_num, linein f.ChangedContents():
3244if impl_pattern.match(line)or v8_wrapper_pattern.match(line):
3245 errors.append(' %s:%d'%(f.LocalPath(), line_num))
Omer Katzcc77ea92021-04-26 10:23:28[diff] [blame]3246
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3247 results=[]
3248if errors:
3249 results.append(
3250 output_api.PresubmitError(
3251'Do not include files from third_party/blink/renderer/platform/heap/impl'
3252' or third_party/blink/renderer/platform/heap/v8_wrapper. Use the '
3253'relevant counterparts from third_party/blink/renderer/platform/heap',
3254 errors))
3255return results
Omer Katzcc77ea92021-04-26 10:23:28[diff] [blame]3256
3257
dbeam@chromium.org70ca77752012-11-20 03:45:03[diff] [blame]3258def_CheckForVersionControlConflictsInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3259 pattern= input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
3260 errors=[]
3261for line_num, linein f.ChangedContents():
3262if f.LocalPath().endswith(('.md','.rst','.txt')):
3263# First-level headers in markdown look a lot like version control
3264# conflict markers. http://daringfireball.net/projects/markdown/basics
3265continue
3266if pattern.match(line):
3267 errors.append(' %s:%d %s'%(f.LocalPath(), line_num, line))
3268return errors
dbeam@chromium.org70ca77752012-11-20 03:45:03[diff] [blame]3269
3270
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3271defCheckForVersionControlConflicts(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3272"""Usually this is not intentional and will cause a compile failure."""
3273 errors=[]
3274for fin input_api.AffectedFiles():
3275 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
dbeam@chromium.org70ca77752012-11-20 03:45:03[diff] [blame]3276
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3277 results=[]
3278if errors:
3279 results.append(
3280 output_api.PresubmitError(
3281'Version control conflict markers found, please resolve.',
3282 errors))
3283return results
dbeam@chromium.org70ca77752012-11-20 03:45:03[diff] [blame]3284
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:20[diff] [blame]3285
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3286defCheckGoogleSupportAnswerUrlOnUpload(input_api, output_api):
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]3287 pattern= input_api.re.compile(r'support\.google\.com\/chrome.*/answer')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3288 errors=[]
3289for fin input_api.AffectedFiles():
3290for line_num, linein f.ChangedContents():
3291if pattern.search(line):
3292 errors.append(' %s:%d %s'%(f.LocalPath(), line_num, line))
estadee17314a02017-01-12 16:22:16[diff] [blame]3293
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3294 results=[]
3295if errors:
3296 results.append(
3297 output_api.PresubmitPromptWarning(
3298'Found Google support URL addressed by answer number. Please replace '
3299'with a p= identifier instead. See crbug.com/679462\n',
3300 errors))
3301return results
estadee17314a02017-01-12 16:22:16[diff] [blame]3302
dbeam@chromium.org70ca77752012-11-20 03:45:03[diff] [blame]3303
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3304defCheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3305
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3306defFilterFile(affected_file):
3307"""Filter function for use with input_api.AffectedSourceFiles,
3308 below. This filters out everything except non-test files from
3309 top-level directories that generally speaking should not hard-code
3310 service URLs (e.g. src/android_webview/, src/content/ and others).
3311 """
3312return input_api.FilterSourceFile(
3313 affected_file,
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3314 files_to_check=[r'^(android_webview|base|content|net)/.*'],
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3315 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
3316 input_api.DEFAULT_FILES_TO_SKIP))
joi@chromium.org06e6d0ff2012-12-11 01:36:44[diff] [blame]3317
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]3318 base_pattern=(r'"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
3319 r'\.(com|net)[^"]*"')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3320 comment_pattern= input_api.re.compile('//.*%s'% base_pattern)
3321 pattern= input_api.re.compile(base_pattern)
3322 problems=[]# items are (filename, line_number, line)
3323for fin input_api.AffectedSourceFiles(FilterFile):
3324for line_num, linein f.ChangedContents():
3325ifnot comment_pattern.search(line)and pattern.search(line):
3326 problems.append((f.LocalPath(), line_num, line))
joi@chromium.org06e6d0ff2012-12-11 01:36:44[diff] [blame]3327
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3328if problems:
3329return[
3330 output_api.PresubmitPromptOrNotify(
3331'Most layers below src/chrome/ should not hardcode service URLs.\n'
3332'Are you sure this is correct?',[
3333' %s:%d: %s'%(problem[0], problem[1], problem[2])
3334for problemin problems
3335])
3336]
3337else:
3338return[]
joi@chromium.org06e6d0ff2012-12-11 01:36:44[diff] [blame]3339
3340
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3341defCheckChromeOsSyncedPrefRegistration(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3342"""Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]3343
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3344defFileFilter(affected_file):
3345"""Includes directories known to be Chrome OS only."""
3346return input_api.FilterSourceFile(
3347 affected_file,
3348 files_to_check=(
3349'^ash/',
3350'^chromeos/',# Top-level src/chromeos.
3351'.*/chromeos/',# Any path component.
3352'^components/arc',
3353'^components/exo'),
3354 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP))
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]3355
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3356 prefs=[]
3357 priority_prefs=[]
3358for fin input_api.AffectedFiles(file_filter=FileFilter):
3359for line_num, linein f.ChangedContents():
3360if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF',
3361 line):
3362 prefs.append(' %s:%d:'%(f.LocalPath(), line_num))
3363 prefs.append(' %s'% line)
3364if input_api.re.search(
3365'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
3366 priority_prefs.append(' %s:%d'%(f.LocalPath(), line_num))
3367 priority_prefs.append(' %s'% line)
3368
3369 results=[]
3370if(prefs):
3371 results.append(
3372 output_api.PresubmitPromptWarning(
3373'Preferences were registered as SYNCABLE_PREF and will be controlled '
3374'by browser sync settings. If these prefs should be controlled by OS '
3375'sync settings use SYNCABLE_OS_PREF instead.\n'+
3376'\n'.join(prefs)))
3377if(priority_prefs):
3378 results.append(
3379 output_api.PresubmitPromptWarning(
3380'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
3381'controlled by browser sync settings. If these prefs should be '
3382'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
3383'instead.\n'+'\n'.join(prefs)))
3384return results
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]3385
3386
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3387defCheckNoAbbreviationInPngFileName(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3388"""Makes sure there are no abbreviations in the name of PNG files.
3389 The native_client_sdk directory is excluded because it has auto-generated PNG
3390 files for documentation.
3391 """
3392 errors=[]
Yuanqing Zhu9eef02832022-12-04 14:42:17[diff] [blame]3393 files_to_check=[r'.*\.png$']
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3394 files_to_skip=[
3395 r'^native_client_sdk/',
3396 r'^services/test/',
3397 r'^third_party/blink/web_tests/',
3398]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3399 file_filter=lambda f: input_api.FilterSourceFile(
3400 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]3401 abbreviation= input_api.re.compile(r'.+_[a-z]\.png|.+_[a-z]_.*\.png')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3402for fin input_api.AffectedFiles(include_deletes=False,
3403 file_filter=file_filter):
Yuanqing Zhu9eef02832022-12-04 14:42:17[diff] [blame]3404 file_name= input_api.os_path.split(f.LocalPath())[1]
3405if abbreviation.search(file_name):
3406 errors.append(' %s'% f.LocalPath())
oshima@chromium.orgd2530012013-01-25 16:39:27[diff] [blame]3407
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3408 results=[]
3409if errors:
3410 results.append(
3411 output_api.PresubmitError(
3412'The name of PNG files should not have abbreviations. \n'
3413'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
3414'Contact oshima@chromium.org if you have questions.', errors))
3415return results
oshima@chromium.orgd2530012013-01-25 16:39:27[diff] [blame]3416
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3417
Evan Stade7cd4a2c2022-08-04 23:37:25[diff] [blame]3418defCheckNoProductIconsAddedToPublicRepo(input_api, output_api):
3419"""Heuristically identifies product icons based on their file name and reminds
3420 contributors not to add them to the Chromium repository.
3421 """
Peter Kotwiczf634d072025-04-28 22:48:15[diff] [blame]3422
3423if input_api.change.RepositoryRoot().endswith('clank'):
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3424# TODO(crbug.com/414435241): Change check to compute whether change
3425# belongs to internal repository instead of relying on string matching.
3426return[]
Peter Kotwiczf634d072025-04-28 22:48:15[diff] [blame]3427
Evan Stade7cd4a2c2022-08-04 23:37:25[diff] [blame]3428 errors=[]
3429 files_to_check=[r'.*google.*\.png$|.*google.*\.svg$|.*google.*\.icon$']
3430 file_filter=lambda f: input_api.FilterSourceFile(
3431 f, files_to_check=files_to_check)
3432for fin input_api.AffectedFiles(include_deletes=False,
3433 file_filter=file_filter):
3434 errors.append(' %s'% f.LocalPath())
3435
3436 results=[]
3437if errors:
Bruce Dawson3bcf0c92022-08-12 00:03:08[diff] [blame]3438# Give warnings instead of errors on presubmit --all and presubmit
3439# --files.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3440 message_type=(output_api.PresubmitNotifyResult
3441if input_api.no_diffselse output_api.PresubmitError)
Evan Stade7cd4a2c2022-08-04 23:37:25[diff] [blame]3442 results.append(
Bruce Dawson3bcf0c92022-08-12 00:03:08[diff] [blame]3443 message_type(
Evan Stade7cd4a2c2022-08-04 23:37:25[diff] [blame]3444'Trademarked images should not be added to the public repo. '
3445'See crbug.com/944754', errors))
3446return results
3447
oshima@chromium.orgd2530012013-01-25 16:39:27[diff] [blame]3448
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3449def_ExtractAddRulesFromParsedDeps(parsed_deps):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3450"""Extract the rules that add dependencies from a parsed DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3451
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3452 Args:
3453 parsed_deps: the locals dictionary from evaluating the DEPS file."""
3454 add_rules= set()
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3455 add_rules.update([
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3456 rule[1:]for rulein parsed_deps.get('include_rules',[])
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3457if rule.startswith('+')or rule.startswith('!')
3458])
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3459for _, rulesin parsed_deps.get('specific_include_rules',{}).items():
3460 add_rules.update([
3461 rule[1:]for rulein rules
3462if rule.startswith('+')or rule.startswith('!')
3463])
3464return add_rules
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3465
3466
3467def_ParseDeps(contents):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3468"""Simple helper for parsing DEPS files."""
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3469
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3470# Stubs for handling special syntax in the root DEPS file.
3471class_VarImpl:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3472
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3473def __init__(self, local_scope):
3474 self._local_scope= local_scope
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3475
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3476defLookup(self, var_name):
3477"""Implements the Var syntax."""
3478try:
3479return self._local_scope['vars'][var_name]
3480exceptKeyError:
3481raiseException('Var is not defined: %s'% var_name)
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3482
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3483 local_scope={}
3484 global_scope={
3485'Var':_VarImpl(local_scope).Lookup,
3486'Str': str,
3487}
Dirk Pranke1b9e06382021-05-14 01:16:22[diff] [blame]3488
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3489exec(contents, global_scope, local_scope)
3490return local_scope
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3491
3492
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3493def_FindAllDepsFilesForSubpath(input_api, subpath):
3494 ret=[]
3495while subpath:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3496 cur= input_api.os_path.join(input_api.change.RepositoryRoot(),
3497 subpath,'DEPS')
Joanna Wang130e7bdd2024-12-10 17:39:03[diff] [blame]3498if input_api.os_path.isfile(cur):
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3499 ret.append(cur)
3500 subpath= input_api.os_path.dirname(subpath)
3501return ret
3502
3503
3504def_FindAddedDepsThatRequireReview(input_api, depended_on_paths):
3505"""Filters to those whose DEPS set new_usages_require_review=True"""
3506 ret= set()
3507 cache={}
3508for target_pathin depended_on_paths:
3509for subpathin_FindAllDepsFilesForSubpath(input_api, target_path):
3510 config= cache.get(subpath)
3511if configisNone:
3512 config=_ParseDeps(input_api.ReadFile(subpath))
3513 cache[subpath]= config
3514if config.get('new_usages_require_review'):
3515 ret.add(target_path)
3516break
3517return ret
3518
3519
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3520def_CalculateAddedDeps(os_path, old_contents, new_contents):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3521"""Helper method for CheckAddedDepsHaveTargetApprovals. Returns
3522 a set of DEPS entries that we should look up.
joi@chromium.org14a6131c2014-01-08 01:15:41[diff] [blame]3523
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3524 For a directory (rather than a specific filename) we fake a path to
3525 a specific filename by adding /DEPS. This is chosen as a file that
3526 will seldom or never be subject to per-file include_rules.
3527 """
3528# We ignore deps entries on auto-generated directories.
3529 AUTO_GENERATED_DIRS=['grit','jni']
tony@chromium.orgf32e2d1e2013-07-26 21:39:08[diff] [blame]3530
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3531 old_deps=_ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
3532 new_deps=_ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3533
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3534 added_deps= new_deps.difference(old_deps)
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]3535
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3536 results= set()
3537for added_depin added_deps:
3538if added_dep.split('/')[0]in AUTO_GENERATED_DIRS:
3539continue
3540# Assume that a rule that ends in .h is a rule for a specific file.
3541if added_dep.endswith('.h'):
3542 results.add(added_dep)
3543else:
3544 results.add(os_path.join(added_dep,'DEPS'))
3545return results
tony@chromium.orgf32e2d1e2013-07-26 21:39:08[diff] [blame]3546
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3547
Stephanie Kimec4f55a2024-04-24 16:54:02[diff] [blame]3548defCheckForNewDEPSDownloadFromGoogleStorageHooks(input_api, output_api):
3549"""Checks that there are no new download_from_google_storage hooks"""
3550for fin input_api.AffectedFiles(include_deletes=False):
3551if f.LocalPath()=='DEPS':
3552 old_hooks=_ParseDeps('\n'.join(f.OldContents()))['hooks']
3553 new_hooks=_ParseDeps('\n'.join(f.NewContents()))['hooks']
3554 old_name_to_hook={hook['name']: hookfor hookin old_hooks}
3555 new_name_to_hook={hook['name']: hookfor hookin new_hooks}
3556 added_hook_names= set(new_name_to_hook.keys())- set(
3557 old_name_to_hook.keys())
3558ifnot added_hook_names:
3559return[]
3560 new_download_from_google_storage_hooks=[]
3561for new_hookin added_hook_names:
3562 hook= new_name_to_hook[new_hook]
3563 action_cmd= hook['action']
3564if any('download_from_google_storage'in arg
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3565for argin action_cmd):
Stephanie Kimec4f55a2024-04-24 16:54:02[diff] [blame]3566 new_download_from_google_storage_hooks.append(new_hook)
3567if new_download_from_google_storage_hooks:
3568return[
3569 output_api.PresubmitError(
3570'Please do not add new download_from_google_storage '
3571'hooks. Instead, add a `gcs` dep_type entry to `deps`. '
3572'See https://chromium.googlesource.com/chromium/src.git'
3573'/+/refs/heads/main/docs/gcs_dependencies.md for more '
3574'info. Added hooks:',
3575 items=new_download_from_google_storage_hooks)
3576]
3577return[]
3578
tony@chromium.orgf32e2d1e2013-07-26 21:39:08[diff] [blame]3579
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3580defCheckEachPerfettoTestDataFileHasDepsEntry(input_api, output_api):
3581 test_data_filter=lambda f: input_api.FilterSourceFile(
Rasika Navarange08e542162024-05-31 13:31:26[diff] [blame]3582 f, files_to_check=[r'^base/tracing/test/data_sha256/.*\.sha256'])
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3583ifnot any(input_api.AffectedFiles(file_filter=test_data_filter)):
3584return[]
3585
3586# Find DEPS entry
3587 deps_entry=[]
Rasika Navarange277cd662024-06-04 10:14:59[diff] [blame]3588 old_deps_entry=[]
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3589for fin input_api.AffectedFiles(include_deletes=False):
3590if f.LocalPath()=='DEPS':
3591 new_deps=_ParseDeps('\n'.join(f.NewContents()))['deps']
3592 deps_entry= new_deps['src/base/tracing/test/data']
Rasika Navarange277cd662024-06-04 10:14:59[diff] [blame]3593 old_deps=_ParseDeps('\n'.join(f.OldContents()))['deps']
3594 old_deps_entry= old_deps['src/base/tracing/test/data']
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3595ifnot deps_entry:
Rasika Navarange08e542162024-05-31 13:31:26[diff] [blame]3596# TODO(312895063):Add back error when .sha256 files have been moved.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3597return[
3598 output_api.PresubmitError(
3599'You must update the DEPS file when you update a '
3600'.sha256 file in base/tracing/test/data_sha256')
3601]
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3602
3603 output=[]
3604for fin input_api.AffectedFiles(file_filter=test_data_filter):
3605 objects= deps_entry['objects']
3606ifnot f.NewContents():
3607# Deleted file so check that DEPS entry removed
3608 sha256_from_file= f.OldContents()[0]
3609 object_entry= next(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3610(item
3611for itemin objectsif item["sha256sum"]== sha256_from_file),
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3612None)
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3613 old_entry= next((itemfor itemin old_deps_entry['objects']
3614if item["sha256sum"]== sha256_from_file),None)
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3615if object_entry:
Rasika Navarange277cd662024-06-04 10:14:59[diff] [blame]3616# Allow renaming of objects with the same hash
3617if object_entry['object_name']!= old_entry['object_name']:
3618continue
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3619 output.append(
3620 output_api.PresubmitError(
3621'You deleted %s so you must also remove the corresponding DEPS entry.'
3622% f.LocalPath()))
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3623continue
3624
3625 sha256_from_file= f.NewContents()[0]
3626 object_entry= next(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3627(item
3628for itemin objectsif item["sha256sum"]== sha256_from_file),
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3629None)
3630ifnot object_entry:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3631 output.append(
3632 output_api.PresubmitError(
3633'No corresponding DEPS entry found for %s. '
3634'Run `base/tracing/test/test_data.py get_deps --filepath %s` '
3635'to generate the DEPS entry.'%
3636(f.LocalPath(), f.LocalPath())))
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3637
3638if output:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3639 output.append(
3640 output_api.PresubmitError(
3641'The DEPS entry for `src/base/tracing/test/data` in the DEPS file has not been '
3642'updated properly. Run `base/tracing/test/test_data.py get_all_deps` to see what '
3643'the DEPS entry should look like.'))
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]3644return output
3645
3646
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3647defCheckAddedDepsHaveTargetApprovals(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3648"""When a dependency prefixed with + is added to a DEPS file, we
3649 want to make sure that the change is reviewed by an OWNER of the
3650 target file or directory, to avoid layering violations from being
3651 introduced. This check verifies that this happens.
3652 """
3653# We rely on Gerrit's code-owners to check approvals.
3654# input_api.gerrit is always set for Chromium, but other projects
3655# might not use Gerrit.
Bruce Dawson344ab262022-06-04 11:35:10[diff] [blame]3656ifnot input_api.gerritor input_api.no_diffs:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3657return[]
Bruce Dawsonb357aeb2022-08-09 15:38:30[diff] [blame]3658if'PRESUBMIT_SKIP_NETWORK'in input_api.environ:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3659return[]
Bruce Dawsonb357aeb2022-08-09 15:38:30[diff] [blame]3660try:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3661if(input_api.change.issue
3662and input_api.gerrit.IsOwnersOverrideApproved(
3663 input_api.change.issue)):
Bruce Dawsonb357aeb2022-08-09 15:38:30[diff] [blame]3664# Skip OWNERS check when Owners-Override label is approved. This is
3665# intended for global owners, trusted bots, and on-call sheriffs.
3666# Review is still required for these changes.
3667return[]
3668exceptExceptionas e:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3669return[
3670 output_api.PresubmitPromptWarning(
3671'Failed to retrieve owner override status - %s'% str(e))
3672]
Edward Lesmes6fba51082021-01-20 04:20:23[diff] [blame]3673
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3674# A set of paths (that might not exist) that are being added as DEPS
3675# (via lines like "+foo/bar/baz").
3676 depended_on_paths= set()
jochen53efcdd2016-01-29 05:09:24[diff] [blame]3677
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3678 file_filter=lambda f:not input_api.re.match(r"^third_party/blink/.*",
3679 f.UnixLocalPath())
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3680for fin input_api.AffectedFiles(include_deletes=False,
3681 file_filter=file_filter):
3682 filename= input_api.os_path.basename(f.LocalPath())
3683if filename=='DEPS':
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3684 depended_on_paths.update(
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3685_CalculateAddedDeps(input_api.os_path,
3686'\n'.join(f.OldContents()),
3687'\n'.join(f.NewContents())))
joi@chromium.orge871964c2013-05-13 14:14:55[diff] [blame]3688
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3689# Requiring reviews is opt-in as of https://crbug.com/365797506
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3690 depended_on_paths=_FindAddedDepsThatRequireReview(
3691 input_api, depended_on_paths)
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3692ifnot depended_on_paths:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3693return[]
joi@chromium.orge871964c2013-05-13 14:14:55[diff] [blame]3694
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3695if input_api.is_committing:
3696if input_api.tbr:
3697return[
3698 output_api.PresubmitNotifyResult(
3699'--tbr was specified, skipping OWNERS check for DEPS additions'
3700)
3701]
Daniel Cheng3008dc12022-05-13 04:02:11[diff] [blame]3702# TODO(dcheng): Make this generate an error on dry runs if the reviewer
3703# is not added, to prevent review serialization.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3704if input_api.dry_run:
3705return[
3706 output_api.PresubmitNotifyResult(
3707'This is a dry run, skipping OWNERS check for DEPS additions'
3708)
3709]
3710ifnot input_api.change.issue:
3711return[
3712 output_api.PresubmitError(
3713"DEPS approval by OWNERS check failed: this change has "
3714"no change number, so we can't check it for approvals.")
3715]
3716 output= output_api.PresubmitError
joi@chromium.org14a6131c2014-01-08 01:15:41[diff] [blame]3717else:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3718 output= output_api.PresubmitNotifyResult
joi@chromium.orge871964c2013-05-13 14:14:55[diff] [blame]3719
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3720 owner_email, reviewers=(
3721 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
3722 input_api,None, approval_needed=input_api.is_committing))
joi@chromium.orge871964c2013-05-13 14:14:55[diff] [blame]3723
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3724 owner_email= owner_emailor input_api.change.author_email
3725
3726 approval_status= input_api.owners_client.GetFilesApprovalStatus(
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3727 depended_on_paths, reviewers.union([owner_email]),[])
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3728 missing_files=[
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]3729 pfor pin depended_on_paths
3730if approval_status[p]!= input_api.owners_client.APPROVED
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3731]
3732
3733# We strip the /DEPS part that was added by
3734# _FilesToCheckForIncomingDeps to fake a path to a file in a
3735# directory.
3736defStripDeps(path):
3737 start_deps= path.rfind('/DEPS')
3738if start_deps!=-1:
3739return path[:start_deps]
3740else:
3741return path
3742
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]3743 submodule_paths= set(input_api.ListSubmodules())
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]3744
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]3745def is_from_submodules(path, submodule_paths):
3746 path= input_api.os_path.normpath(path)
3747while path:
3748if pathin submodule_paths:
3749returnTrue
3750
3751# All deps should be a relative path from the checkout.
3752# i.e., shouldn't start with "/" or "c:\", for example.
3753#
3754# That said, this is to prevent an infinite loop, just in case
3755# an input dep path starts with "/", because
3756# os.path.dirname("/") => "/"
3757 parent= input_api.os_path.dirname(path)
3758if parent== path:
3759break
3760 path= parent
3761
3762returnFalse
3763
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3764 unapproved_dependencies=[
3765"'+%s',"%StripDeps(path)for pathin missing_files
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]3766# if a newly added dep is from a submodule, it becomes trickier
3767# to get suggested owners, especially it is from a different host.
3768#
3769# skip the review enforcement for cross-repo deps.
3770ifnot is_from_submodules(path, submodule_paths)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3771]
3772
3773if unapproved_dependencies:
3774 output_list=[
3775 output(
3776'You need LGTM from owners of depends-on paths in DEPS that were '
3777'modified in this CL:\n %s'%
3778'\n '.join(sorted(unapproved_dependencies)))
3779]
3780 suggested_owners= input_api.owners_client.SuggestOwners(
3781 missing_files, exclude=[owner_email])
3782 output_list.append(
3783 output('Suggested missing target path OWNERS:\n %s'%
3784'\n '.join(suggested_ownersor[])))
3785return output_list
3786
3787return[]
joi@chromium.orge871964c2013-05-13 14:14:55[diff] [blame]3788
3789
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:49[diff] [blame]3790# TODO: add unit tests.
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3791defCheckSpamLogging(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3792 file_inclusion_pattern=[r'.+%s'% _IMPLEMENTATION_EXTENSIONS]
3793 files_to_skip=(
3794 _EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
3795 input_api.DEFAULT_FILES_TO_SKIP+(
Jaewon Jung2f323bb2022-12-07 23:55:01[diff] [blame]3796 r"^base/fuchsia/scoped_fx_logger\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3797 r"^base/logging\.h$",
3798 r"^base/logging\.cc$",
3799 r"^base/task/thread_pool/task_tracker\.cc$",
3800 r"^chrome/app/chrome_main_delegate\.cc$",
Yao Li359937b2023-02-15 23:43:03[diff] [blame]3801 r"^chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer\.cc$",
3802 r"^chrome/browser/ash/policy/remote_commands/user_command_arc_job\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3803 r"^chrome/browser/chrome_browser_main\.cc$",
3804 r"^chrome/browser/ui/startup/startup_browser_creator\.cc$",
3805 r"^chrome/browser/browser_switcher/bho/.*",
3806 r"^chrome/browser/diagnostics/diagnostics_writer\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3807 r"^chrome/chrome_elf/dll_hash/dll_hash_main\.cc$",
3808 r"^chrome/installer/setup/.*",
Daniel Ruberyad36eea2024-08-01 01:38:32[diff] [blame]3809# crdmg runs as a separate binary which intentionally does
3810# not depend on base logging.
3811 r"^chrome/utility/safe_browsing/mac/crdmg\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3812 r"^chromecast/",
Vigen Issahhanjane2d93822023-06-30 15:57:20[diff] [blame]3813 r"^components/cast",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3814 r"^components/media_control/renderer/media_playback_options\.cc$",
Salma Elmahallawy52976452023-01-27 17:04:49[diff] [blame]3815 r"^components/policy/core/common/policy_logger\.cc$",
Tomek Jurkiewicz06fd6a72025-06-18 15:24:28[diff] [blame]3816 r"^components/supervised_user/core/browser/android/content_filters_observer_bridge\.cc",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3817 r"^components/viz/service/display/"
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3818 r"overlay_strategy_underlay_cast\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3819 r"^components/zucchini/.*",
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3820# TODO(peter): Remove exception. https://crbug.com/534537
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3821 r"^content/browser/notifications/"
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3822 r"notification_event_dispatcher_impl\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3823 r"^content/common/gpu/client/gl_helper_benchmark\.cc$",
3824 r"^courgette/courgette_minimal_tool\.cc$",
3825 r"^courgette/courgette_tool\.cc$",
3826 r"^extensions/renderer/logging_native_handler\.cc$",
3827 r"^fuchsia_web/common/init_logging\.cc$",
3828 r"^fuchsia_web/runners/common/web_component\.cc$",
Caroline Liua7050132023-02-13 22:23:15[diff] [blame]3829 r"^fuchsia_web/shell/.*\.cc$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3830 r"^headless/app/headless_shell\.cc$",
3831 r"^ipc/ipc_logging\.cc$",
3832 r"^native_client_sdk/",
3833 r"^remoting/base/logging\.h$",
3834 r"^remoting/host/.*",
3835 r"^sandbox/linux/.*",
Austin Sullivana6054e02024-05-20 16:31:29[diff] [blame]3836 r"^services/webnn/tflite/graph_impl_tflite\.cc$",
3837 r"^services/webnn/coreml/graph_impl_coreml\.mm$",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3838 r"^storage/browser/file_system/dump_file_system\.cc$",
Steinar H. Gundersone5689e42024-08-07 18:17:19[diff] [blame]3839 r"^testing/perf/",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]3840 r"^tools/",
3841 r"^ui/base/resource/data_pack\.cc$",
3842 r"^ui/aura/bench/bench_main\.cc$",
3843 r"^ui/ozone/platform/cast/",
3844 r"^ui/base/x/xwmstartupcheck/"
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3845 r"xwmstartupcheck\.cc$"))
3846 source_file_filter=lambda x: input_api.FilterSourceFile(
3847 x, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
thakis@chromium.org85218562013-11-22 07:41:40[diff] [blame]3848
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3849 log_info= set([])
3850 printf= set([])
thakis@chromium.org85218562013-11-22 07:41:40[diff] [blame]3851
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3852for fin input_api.AffectedSourceFiles(source_file_filter):
3853for _, linein f.ChangedContents():
3854if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
3855 log_info.add(f.LocalPath())
3856elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
3857 log_info.add(f.LocalPath())
jln@chromium.org18b466b2013-12-02 22:01:37[diff] [blame]3858
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3859if input_api.re.search(r"\bprintf\(", line):
3860 printf.add(f.LocalPath())
3861elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
3862 printf.add(f.LocalPath())
thakis@chromium.org85218562013-11-22 07:41:40[diff] [blame]3863
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3864if log_info:
3865return[
3866 output_api.PresubmitError(
3867'These files spam the console log with LOG(INFO):',
3868 items=log_info)
3869]
3870if printf:
3871return[
3872 output_api.PresubmitError(
3873'These files spam the console log with printf/fprintf:',
3874 items=printf)
3875]
3876return[]
thakis@chromium.org85218562013-11-22 07:41:40[diff] [blame]3877
3878
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3879defCheckForAnonymousVariables(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3880"""These types are all expected to hold locks while in scope and
3881 so should never be anonymous (which causes them to be immediately
3882 destroyed)."""
3883 they_who_must_be_named=[
3884'base::AutoLock',
3885'base::AutoReset',
3886'base::AutoUnlock',
3887'SkAutoAlphaRestore',
3888'SkAutoBitmapShaderInstall',
3889'SkAutoBlitterChoose',
3890'SkAutoBounderCommit',
3891'SkAutoCallProc',
3892'SkAutoCanvasRestore',
3893'SkAutoCommentBlock',
3894'SkAutoDescriptor',
3895'SkAutoDisableDirectionCheck',
3896'SkAutoDisableOvalCheck',
3897'SkAutoFree',
3898'SkAutoGlyphCache',
3899'SkAutoHDC',
3900'SkAutoLockColors',
3901'SkAutoLockPixels',
3902'SkAutoMalloc',
3903'SkAutoMaskFreeImage',
3904'SkAutoMutexAcquire',
3905'SkAutoPathBoundsUpdate',
3906'SkAutoPDFRelease',
3907'SkAutoRasterClipValidate',
3908'SkAutoRef',
3909'SkAutoTime',
3910'SkAutoTrace',
3911'SkAutoUnref',
3912]
3913 anonymous= r'(%s)\s*[({]'%'|'.join(they_who_must_be_named)
3914# bad: base::AutoLock(lock.get());
3915# not bad: base::AutoLock lock(lock.get());
3916 bad_pattern= input_api.re.compile(anonymous)
3917# good: new base::AutoLock(lock.get())
3918 good_pattern= input_api.re.compile(r'\bnew\s*'+ anonymous)
3919 errors=[]
enne@chromium.org49aa76a2013-12-04 06:59:16[diff] [blame]3920
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3921for fin input_api.AffectedFiles():
3922ifnot f.LocalPath().endswith(('.cc','.h','.inl','.m','.mm')):
3923continue
3924for linenum, linein f.ChangedContents():
3925if bad_pattern.search(line)andnot good_pattern.search(line):
3926 errors.append('%s:%d'%(f.LocalPath(), linenum))
enne@chromium.org49aa76a2013-12-04 06:59:16[diff] [blame]3927
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3928if errors:
3929return[
3930 output_api.PresubmitError(
3931'These lines create anonymous variables that need to be named:',
3932 items=errors)
3933]
3934return[]
enne@chromium.org49aa76a2013-12-04 06:59:16[diff] [blame]3935
3936
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]3937defCheckUniquePtrOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3938# Returns whether |template_str| is of the form <T, U...> for some types T
Glen Robertson9142ffd72024-05-16 01:37:47[diff] [blame]3939# and U, or is invalid due to mismatched angle bracket pairs. Assumes that
3940# |template_str| is already in the form <...>.
3941defHasMoreThanOneArgOrInvalid(template_str):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3942# Level of <...> nesting.
3943 nesting=0
3944for cin template_str:
3945if c=='<':
3946 nesting+=1
3947elif c=='>':
3948 nesting-=1
3949elif c==','and nesting==1:
3950returnTrue
Glen Robertson9142ffd72024-05-16 01:37:47[diff] [blame]3951if nesting!=0:
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3952# Invalid.
3953returnTrue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3954returnFalse
Vaclav Brozekb7fadb692018-08-30 06:39:53[diff] [blame]3955
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3956 file_inclusion_pattern=[r'.+%s'% _IMPLEMENTATION_EXTENSIONS]
3957 sources=lambda affected_file: input_api.FilterSourceFile(
3958 affected_file,
3959 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+ input_api.
3960 DEFAULT_FILES_TO_SKIP),
3961 files_to_check=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:55[diff] [blame]3962
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3963# Pattern to capture a single "<...>" block of template arguments. It can
3964# handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
3965# cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
3966# latter would likely require counting that < and > match, which is not
3967# expressible in regular languages. Should the need arise, one can introduce
3968# limited counting (matching up to a total number of nesting depth), which
3969# should cover all practical cases for already a low nesting limit.
3970 template_arg_pattern=(
3971 r'<[^>]*'# Opening block of <.
3972 r'>([^<]*>)?')# Closing block of >.
3973# Prefix expressing that whatever follows is not already inside a <...>
3974# block.
3975 not_inside_template_arg_pattern= r'(^|[^<,\s]\s*)'
3976 null_construct_pattern= input_api.re.compile(
3977 not_inside_template_arg_pattern+ r'\bstd::unique_ptr'+
3978 template_arg_pattern+ r'\(\)')
Vaclav Brozeka54c528b2018-04-06 19:23:55[diff] [blame]3979
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3980# Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
3981 template_arg_no_array_pattern=(
3982 r'<[^>]*[^]]'# Opening block of <.
3983 r'>([^(<]*[^]]>)?')# Closing block of >.
3984# Prefix saying that what follows is the start of an expression.
3985 start_of_expr_pattern= r'(=|\breturn|^)\s*'
3986# Suffix saying that what follows are call parentheses with a non-empty list
3987# of arguments.
3988 nonempty_arg_list_pattern= r'\(([^)]|$)'
3989# Put the template argument into a capture group for deeper examination later.
3990 return_construct_pattern= input_api.re.compile(
3991 start_of_expr_pattern+ r'std::unique_ptr'+'(?P<template_arg>'+
3992 template_arg_no_array_pattern+')'+ nonempty_arg_list_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:55[diff] [blame]3993
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]3994 problems_constructor=[]
3995 problems_nullptr=[]
3996for fin input_api.AffectedSourceFiles(sources):
3997for line_number, linein f.ChangedContents():
3998# Disallow:
3999# return std::unique_ptr<T>(foo);
4000# bar = std::unique_ptr<T>(foo);
4001# But allow:
4002# return std::unique_ptr<T[]>(foo);
4003# bar = std::unique_ptr<T[]>(foo);
4004# And also allow cases when the second template argument is present. Those
4005# cases cannot be handled by std::make_unique:
4006# return std::unique_ptr<T, U>(foo);
4007# bar = std::unique_ptr<T, U>(foo);
4008 local_path= f.LocalPath()
4009 return_construct_result= return_construct_pattern.search(line)
Glen Robertson9142ffd72024-05-16 01:37:47[diff] [blame]4010if return_construct_resultandnotHasMoreThanOneArgOrInvalid(
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4011 return_construct_result.group('template_arg')):
4012 problems_constructor.append(
4013'%s:%d\n %s'%(local_path, line_number, line.strip()))
4014# Disallow:
4015# std::unique_ptr<T>()
4016if null_construct_pattern.search(line):
4017 problems_nullptr.append(
4018'%s:%d\n %s'%(local_path, line_number, line.strip()))
Vaclav Brozek851d9602018-04-04 16:13:05[diff] [blame]4019
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4020 errors=[]
4021if problems_nullptr:
4022 errors.append(
4023 output_api.PresubmitPromptWarning(
4024'The following files use std::unique_ptr<T>(). Use nullptr instead.',
4025 problems_nullptr))
4026if problems_constructor:
4027 errors.append(
4028 output_api.PresubmitError(
4029'The following files use explicit std::unique_ptr constructor. '
4030'Use std::make_unique<T>() instead, or use base::WrapUnique if '
4031'std::make_unique is not an option.', problems_constructor))
4032return errors
Peter Kasting4844e46e2018-02-23 07:27:10[diff] [blame]4033
4034
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]4035defCheckUserActionUpdate(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4036"""Checks if any new user action has been added."""
4037if any('actions.xml'== input_api.os_path.basename(f)
4038for fin input_api.LocalPaths()):
4039# If actions.xml is already included in the changelist, the PRESUBMIT
4040# for actions.xml will do a more complete presubmit check.
4041return[]
4042
4043 file_inclusion_pattern=[r'.*\.(cc|mm)$']
4044 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
4045 input_api.DEFAULT_FILES_TO_SKIP)
4046 file_filter=lambda f: input_api.FilterSourceFile(
4047 f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
4048
4049 action_re= r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
4050 current_actions=None
4051for fin input_api.AffectedFiles(file_filter=file_filter):
4052for line_num, linein f.ChangedContents():
4053 match= input_api.re.search(action_re, line)
4054if match:
4055# Loads contents in tools/metrics/actions/actions.xml to memory. It's
4056# loaded only once.
4057ifnot current_actions:
Bruce Dawson6cb2d4d2023-03-01 21:35:09[diff] [blame]4058with open('tools/metrics/actions/actions.xml',
4059 encoding='utf-8')as actions_f:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4060 current_actions= actions_f.read()
4061# Search for the matched user action name in |current_actions|.
4062for action_namein match.groups():
4063 action='name="{0}"'.format(action_name)
4064if actionnotin current_actions:
4065return[
4066 output_api.PresubmitPromptWarning(
4067'File %s line %d: %s is missing in '
4068'tools/metrics/actions/actions.xml. Please run '
4069'tools/metrics/actions/extract_actions.py to update.'
4070%(f.LocalPath(), line_num, action_name))
4071]
yiyaoliu@chromium.org999261d2014-03-03 20:08:08[diff] [blame]4072return[]
4073
yiyaoliu@chromium.org999261d2014-03-03 20:08:08[diff] [blame]4074
Daniel Cheng13ca61a882017-08-25 15:11:25[diff] [blame]4075def_ImportJSONCommentEater(input_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4076import sys
4077 sys.path= sys.path+[
4078 input_api.os_path.join(input_api.PresubmitLocalPath(),'tools',
4079'json_comment_eater')
4080]
4081import json_comment_eater
4082return json_comment_eater
Daniel Cheng13ca61a882017-08-25 15:11:25[diff] [blame]4083
4084
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]4085def_GetJSONParseError(input_api, filename, eat_comments=True):
dchenge07de812016-06-20 19:27:17[diff] [blame]4086try:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4087 contents= input_api.ReadFile(filename)
4088if eat_comments:
4089 json_comment_eater=_ImportJSONCommentEater(input_api)
4090 contents= json_comment_eater.Nom(contents)
dchenge07de812016-06-20 19:27:17[diff] [blame]4091
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4092 input_api.json.loads(contents)
4093exceptValueErroras e:
4094return e
Andrew Grieve4deedb12022-02-03 21:34:50[diff] [blame]4095returnNone
4096
4097
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4098def_GetIDLParseError(input_api, filename):
4099try:
4100 contents= input_api.ReadFile(filename)
Devlin Croninf7582a12022-04-21 21:14:28[diff] [blame]4101for i, charin enumerate(contents):
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4102ifnot char.isascii():
4103return(
4104'Non-ascii character "%s" (ord %d) found at offset %d.'%
4105(char, ord(char), i))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4106 idl_schema= input_api.os_path.join(input_api.PresubmitLocalPath(),
4107'tools','json_schema_compiler',
4108'idl_schema.py')
4109 process= input_api.subprocess.Popen(
Bruce Dawson679fb082022-04-14 00:47:28[diff] [blame]4110[input_api.python3_executable, idl_schema],
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4111 stdin=input_api.subprocess.PIPE,
4112 stdout=input_api.subprocess.PIPE,
4113 stderr=input_api.subprocess.PIPE,
4114 universal_newlines=True)
4115(_, error)= process.communicate(input=contents)
4116return errororNone
4117exceptValueErroras e:
4118return e
agrievef32bcc72016-04-04 14:57:40[diff] [blame]4119
agrievef32bcc72016-04-04 14:57:40[diff] [blame]4120
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4121defCheckParseErrors(input_api, output_api):
4122"""Check that IDL and JSON files do not contain syntax errors."""
4123 actions={
4124'.idl':_GetIDLParseError,
4125'.json':_GetJSONParseError,
4126}
4127# Most JSON files are preprocessed and support comments, but these do not.
4128 json_no_comments_patterns=[
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4129 r'^testing/',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4130]
4131# Only run IDL checker on files in these directories.
4132 idl_included_patterns=[
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4133 r'^chrome/common/extensions/api/',
4134 r'^extensions/common/api/',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4135]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]4136
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4137def get_action(affected_file):
4138 filename= affected_file.LocalPath()
4139return actions.get(input_api.os_path.splitext(filename)[1])
agrievef32bcc72016-04-04 14:57:40[diff] [blame]4140
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4141defFilterFile(affected_file):
4142 action= get_action(affected_file)
4143ifnot action:
4144returnFalse
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]4145 path= affected_file.UnixLocalPath()
agrievef32bcc72016-04-04 14:57:40[diff] [blame]4146
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4147if_MatchesFile(input_api,
4148 _KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS, path):
4149returnFalse
4150
4151if(action==_GetIDLParseError
4152andnot_MatchesFile(input_api, idl_included_patterns, path)):
4153returnFalse
4154returnTrue
4155
4156 results=[]
4157for affected_filein input_api.AffectedFiles(file_filter=FilterFile,
4158 include_deletes=False):
4159 action= get_action(affected_file)
4160 kwargs={}
4161if(action==_GetJSONParseError
4162and_MatchesFile(input_api, json_no_comments_patterns,
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]4163 affected_file.UnixLocalPath())):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4164 kwargs['eat_comments']=False
4165 parse_error= action(input_api, affected_file.AbsoluteLocalPath(),
4166**kwargs)
4167if parse_error:
4168 results.append(
4169 output_api.PresubmitError(
4170'%s could not be parsed: %s'%
4171(affected_file.LocalPath(), parse_error)))
4172return results
4173
4174
4175defCheckJavaStyle(input_api, output_api):
4176"""Runs checkstyle on changed java files and returns errors if any exist."""
4177
4178# Return early if no java files were modified.
4179ifnot any(
4180_IsJavaFile(input_api, f.LocalPath())
4181for fin input_api.AffectedFiles()):
4182return[]
4183
4184import sys
4185 original_sys_path= sys.path
4186try:
4187 sys.path= sys.path+[
4188 input_api.os_path.join(input_api.PresubmitLocalPath(),'tools',
4189'android','checkstyle')
4190]
4191import checkstyle
4192finally:
4193# Restore sys.path to what it was before.
4194 sys.path= original_sys_path
4195
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4196return checkstyle.run_presubmit(input_api,
4197 output_api,
4198 files_to_skip=_EXCLUDED_PATHS+
4199 input_api.DEFAULT_FILES_TO_SKIP)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4200
4201
4202defCheckPythonDevilInit(input_api, output_api):
4203"""Checks to make sure devil is initialized correctly in python scripts."""
4204 script_common_initialize_pattern= input_api.re.compile(
4205 r'script_common\.InitializeEnvironment\(')
4206 devil_env_config_initialize= input_api.re.compile(
4207 r'devil_env\.config\.Initialize\(')
4208
4209 errors=[]
4210
4211 sources=lambda affected_file: input_api.FilterSourceFile(
4212 affected_file,
4213 files_to_skip=(_EXCLUDED_PATHS+ input_api.DEFAULT_FILES_TO_SKIP+(
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4214 r'^build/android/devil_chromium\.py',
Sven Zheng8e079562024-05-10 20:11:06[diff] [blame]4215 r'^tools/bisect-builds\.py',
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4216 r'^third_party/.*',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4217)),
4218 files_to_check=[r'.*\.py$'])
4219
4220for fin input_api.AffectedSourceFiles(sources):
4221for line_num, linein f.ChangedContents():
4222if(script_common_initialize_pattern.search(line)
4223or devil_env_config_initialize.search(line)):
4224 errors.append("%s:%d"%(f.LocalPath(), line_num))
4225
4226 results=[]
4227
4228if errors:
4229 results.append(
4230 output_api.PresubmitError(
4231'Devil initialization should always be done using '
4232'devil_chromium.Initialize() in the chromium project, to use better '
4233'defaults for dependencies (ex. up-to-date version of adb).',
4234 errors))
4235
4236return results
4237
4238
4239def_MatchesFile(input_api, patterns, path):
4240for patternin patterns:
4241if input_api.re.search(pattern, path):
4242returnTrue
4243returnFalse
4244
4245
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4246def_ChangeHasSecurityReviewer(input_api, owners_file):
4247"""Returns True iff the CL has a reviewer from SECURITY_OWNERS.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4248
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4249 Args:
4250 input_api: The presubmit input API.
4251 owners_file: OWNERS file with required reviewers. Typically, this is
4252 something like ipc/SECURITY_OWNERS.
4253
4254 Note: if the presubmit is running for commit rather than for upload, this
4255 only returns True if a security reviewer has also approved the CL.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4256 """
Daniel Chengd88244472022-05-16 09:08:47[diff] [blame]4257# Owners-Override should bypass all additional OWNERS enforcement checks.
4258# A CR+1 vote will still be required to land this change.
4259if(input_api.change.issueand input_api.gerrit.IsOwnersOverrideApproved(
4260 input_api.change.issue)):
4261returnTrue
4262
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4263 owner_email, reviewers=(
4264 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
Daniel Cheng3008dc12022-05-13 04:02:11[diff] [blame]4265 input_api,
4266None,
4267 approval_needed=input_api.is_committingandnot input_api.dry_run))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4268
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4269 security_owners= input_api.owners_client.ListOwners(owners_file)
4270return any(ownerin reviewersfor ownerin security_owners)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4271
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4272
4273@dataclass
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4274class_SecurityProblemWithItems:
4275 problem: str
4276 items:Sequence[str]
4277
4278
4279@dataclass
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4280class_MissingSecurityOwnersResult:
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4281 owners_file_problems:Sequence[_SecurityProblemWithItems]
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4282 has_security_sensitive_files: bool
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4283 missing_reviewer_problem:Optional[_SecurityProblemWithItems]
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4284
4285
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4286def_FindMissingSecurityOwners(
4287 input_api,
4288 output_api,
4289 file_patterns:Sequence[str],
4290 excluded_patterns:Sequence[str],
4291 required_owners_file: str,
4292 custom_rule_function:Optional[Callable]=None
4293)->_MissingSecurityOwnersResult:
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4294"""Find OWNERS files missing per-file rules for security-sensitive files.
4295
4296 Args:
4297 input_api: the PRESUBMIT input API object.
4298 output_api: the PRESUBMIT output API object.
4299 file_patterns: basename patterns that require a corresponding per-file
4300 security restriction.
4301 excluded_patterns: path patterns that should be exempted from
4302 requiring a security restriction.
4303 required_owners_file: path to the required OWNERS file, e.g.
4304 ipc/SECURITY_OWNERS
4305 cc_alias: If not None, email that will be CCed automatically if the
4306 change contains security-sensitive files, as determined by
4307 `file_patterns` and `excluded_patterns`.
4308 custom_rule_function: If not None, will be called with `input_api` and
4309 the current file under consideration. Returning True will add an
4310 exact match per-file rule check for the current file.
4311 """
4312
4313# `to_check` is a mapping of an OWNERS file path to Patterns.
4314#
4315# Patterns is a dictionary mapping glob patterns (suitable for use in
4316# per-file rules) to a PatternEntry.
4317#
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4318# PatternEntry is a dictionary with two keys:
4319# - 'files': the files that are matched by this pattern
4320# - 'rules': the per-file rules needed for this pattern
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4321#
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4322# For example, if we expect OWNERS file to contain rules for *.mojom and
4323# *_struct_traits*.*, Patterns might look like this:
4324# {
4325# '*.mojom': {
4326# 'files': ...,
4327# 'rules': [
4328# 'per-file *.mojom=set noparent',
4329# 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
4330# ],
4331# },
4332# '*_struct_traits*.*': {
4333# 'files': ...,
4334# 'rules': [
4335# 'per-file *_struct_traits*.*=set noparent',
4336# 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
4337# ],
4338# },
4339# }
4340 to_check={}
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4341 files_to_review=[]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4342
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4343defAddPatternToCheck(file, pattern):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4344 owners_file= input_api.os_path.join(
Daniel Chengd88244472022-05-16 09:08:47[diff] [blame]4345 input_api.os_path.dirname(file.LocalPath()),'OWNERS')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4346if owners_filenotin to_check:
4347 to_check[owners_file]={}
4348if patternnotin to_check[owners_file]:
4349 to_check[owners_file][pattern]={
4350'files':[],
4351'rules':[
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4352 f'per-file {pattern}=set noparent',
4353 f'per-file {pattern}=file://{required_owners_file}',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4354]
4355}
Daniel Chenged57a162022-05-25 02:56:34[diff] [blame]4356 to_check[owners_file][pattern]['files'].append(file.LocalPath())
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4357 files_to_review.append(file.LocalPath())
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4358
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4359# Only enforce security OWNERS rules for a directory if that directory has a
4360# file that matches `file_patterns`. For example, if a directory only
4361# contains *.mojom files and no *_messages*.h files, the check should only
4362# ensure that rules for *.mojom files are present.
4363for filein input_api.AffectedFiles(include_deletes=False):
4364 file_basename= input_api.os_path.basename(file.LocalPath())
4365if custom_rule_functionisnotNoneand custom_rule_function(
4366 input_api, file):
4367AddPatternToCheck(file, file_basename)
4368continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4369
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4370if any(
4371 input_api.fnmatch.fnmatch(file.LocalPath(), pattern)
4372for patternin excluded_patterns):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4373continue
4374
4375for patternin file_patterns:
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4376# Unlike `excluded_patterns`, `file_patterns` is checked only against the
4377# file's basename.
4378if input_api.fnmatch.fnmatch(file_basename, pattern):
4379AddPatternToCheck(file, pattern)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4380break
4381
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4382 has_security_sensitive_files= bool(to_check)
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4383
4384# Check if any newly added lines in OWNERS files intersect with required
4385# per-file OWNERS lines. If so, ensure that a security reviewer is included.
4386# This is a hack, but is needed because the OWNERS check (by design) ignores
4387# new OWNERS entries; otherwise, a non-owner could add someone as a new
4388# OWNER and have that newly-added OWNER self-approve their own addition.
4389 newly_covered_files=[]
4390for filein input_api.AffectedFiles(include_deletes=False):
4391ifnot file.LocalPath()in to_check:
4392continue
4393for _, linein file.ChangedContents():
4394for _, entryin to_check[file.LocalPath()].items():
4395if linein entry['rules']:
4396 newly_covered_files.extend(entry['files'])
4397
4398 missing_reviewer_problems=None
4399if newly_covered_filesandnot_ChangeHasSecurityReviewer(
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4400 input_api, required_owners_file):
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4401 missing_reviewer_problems=_SecurityProblemWithItems(
4402 f'Review from an owner in {required_owners_file} is required for '
4403'the following newly-added files:',
4404[f'{file}'for filein sorted(set(newly_covered_files))])
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4405
4406# Go through the OWNERS files to check, filtering out rules that are already
4407# present in that OWNERS file.
4408for owners_file, patternsin to_check.items():
4409try:
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4410 lines= set(
4411 input_api.ReadFile(
4412 input_api.os_path.join(input_api.change.RepositoryRoot(),
4413 owners_file)).splitlines())
4414for entryin patterns.values():
4415 entry['rules']=[
4416 rulefor rulein entry['rules']if rulenotin lines
4417]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4418exceptIOError:
4419# No OWNERS file, so all the rules are definitely missing.
4420continue
4421
4422# All the remaining lines weren't found in OWNERS files, so emit an error.
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4423 owners_file_problems=[]
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4424
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4425for owners_file, patternsin to_check.items():
4426 missing_lines=[]
4427 files=[]
4428for _, entryin patterns.items():
Daniel Chenged57a162022-05-25 02:56:34[diff] [blame]4429 files.extend(entry['files'])
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4430 missing_lines.extend(entry['rules'])
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4431if missing_lines:
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4432 joined_missing_lines='\n'.join(linefor linein missing_lines)
4433 owners_file_problems.append(
4434_SecurityProblemWithItems(
4435'Found missing OWNERS lines for security-sensitive files. '
4436 f'Please add the following lines to {owners_file}:\n'
4437 f'{joined_missing_lines}\n\nTo ensure security review for:',
4438 files))
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4439
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4440return_MissingSecurityOwnersResult(owners_file_problems,
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4441 has_security_sensitive_files,
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4442 missing_reviewer_problems)
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4443
4444
4445def_CheckChangeForIpcSecurityOwners(input_api, output_api):
4446# Whether or not a file affects IPC is (mostly) determined by a simple list
4447# of filename patterns.
4448 file_patterns=[
4449# Legacy IPC:
4450'*_messages.cc',
4451'*_messages*.h',
4452'*_param_traits*.*',
4453# Mojo IPC:
4454'*.mojom',
4455'*_mojom_traits*.*',
4456'*_type_converter*.*',
4457# Android native IPC:
4458'*.aidl',
4459]
4460
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4461 excluded_patterns=[
Daniel Cheng518943f2022-05-12 22:15:46[diff] [blame]4462# These third_party directories do not contain IPCs, but contain files
4463# matching the above patterns, which trigger false positives.
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4464'third_party/crashpad/*',
4465'third_party/blink/renderer/platform/bindings/*',
Evan Stade23a77da2025-02-06 21:15:31[diff] [blame]4466'third_party/protobuf/*',
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4467'third_party/win_build_output/*',
Daniel Chengd88244472022-05-16 09:08:47[diff] [blame]4468# Enum-only mojoms used for web metrics, so no security review needed.
4469'third_party/blink/public/mojom/use_counter/metrics/*',
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4470# These files are just used to communicate between class loaders running
4471# in the same process.
4472'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
4473'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
4474]
4475
4476defIsMojoServiceManifestFile(input_api, file):
Dirk Prankee4df27972025-02-26 18:39:35[diff] [blame]4477 manifest_pattern= input_api.re.compile(r'manifests?\.(cc|h)$')
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4478 test_manifest_pattern= input_api.re.compile(
4479 r'test_manifests?\.(cc|h)')
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4480ifnot manifest_pattern.search(file.LocalPath()):
4481returnFalse
4482
4483if test_manifest_pattern.search(file.LocalPath()):
4484returnFalse
4485
4486# All actual service manifest files should contain at least one
4487# qualified reference to service_manager::Manifest.
4488return any('service_manager::Manifest'in line
4489for linein file.NewContents())
4490
4491return_FindMissingSecurityOwners(
4492 input_api,
4493 output_api,
4494 file_patterns,
4495 excluded_patterns,
4496'ipc/SECURITY_OWNERS',
4497 custom_rule_function=IsMojoServiceManifestFile)
4498
4499
4500def_CheckChangeForFuchsiaSecurityOwners(input_api, output_api):
4501 file_patterns=[
4502# Component specifications.
4503'*.cml',# Component Framework v2.
4504'*.cmx',# Component Framework v1.
4505
4506# Fuchsia IDL protocol specifications.
4507'*.fidl',
4508]
4509
4510# Don't check for owners files for changes in these directories.
4511 excluded_patterns=[
4512'third_party/crashpad/*',
4513]
4514
4515return_FindMissingSecurityOwners(input_api, output_api, file_patterns,
4516 excluded_patterns,
4517'build/fuchsia/SECURITY_OWNERS')
4518
4519
4520defCheckSecurityOwners(input_api, output_api):
4521"""Checks that various security-sensitive files have an IPC OWNERS rule."""
4522 ipc_results=_CheckChangeForIpcSecurityOwners(input_api, output_api)
4523 fuchsia_results=_CheckChangeForFuchsiaSecurityOwners(
4524 input_api, output_api)
4525
4526if ipc_results.has_security_sensitive_files:
4527 output_api.AppendCC('ipc-security-reviews@chromium.org')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4528
4529 results=[]
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4530
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4531 missing_reviewer_problems=[]
4532if ipc_results.missing_reviewer_problem:
4533 missing_reviewer_problems.append(ipc_results.missing_reviewer_problem)
4534if fuchsia_results.missing_reviewer_problem:
4535 missing_reviewer_problems.append(
4536 fuchsia_results.missing_reviewer_problem)
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4537
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4538# Missing reviewers are an error unless there's no issue number
4539# associated with this branch; in that case, the presubmit is being run
4540# with --all or --files.
4541#
4542# Note that upload should never be an error; otherwise, it would be
4543# impossible to upload changes at all.
4544if input_api.is_committingand input_api.change.issue:
4545 make_presubmit_message= output_api.PresubmitError
4546else:
4547 make_presubmit_message= output_api.PresubmitNotifyResult
4548for problemin missing_reviewer_problems:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4549 results.append(
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4550 make_presubmit_message(problem.problem, items=problem.items))
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4551
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4552 owners_file_problems=[]
4553 owners_file_problems.extend(ipc_results.owners_file_problems)
4554 owners_file_problems.extend(fuchsia_results.owners_file_problems)
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4555
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4556for problemin owners_file_problems:
Daniel Cheng3008dc12022-05-13 04:02:11[diff] [blame]4557# Missing per-file rules are always an error. While swarming and caching
4558# means that uploading a patchset with updated OWNERS files and sending
4559# it to the CQ again should not have a large incremental cost, it is
4560# still frustrating to discover the error only after the change has
4561# already been uploaded.
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4562 results.append(
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]4563 output_api.PresubmitError(problem.problem, items=problem.items))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4564
4565return results
4566
4567
4568def_GetFilesUsingSecurityCriticalFunctions(input_api):
4569"""Checks affected files for changes to security-critical calls. This
4570 function checks the full change diff, to catch both additions/changes
4571 and removals.
4572
4573 Returns a dict keyed by file name, and the value is a set of detected
4574 functions.
4575 """
4576# Map of function pretty name (displayed in an error) to the pattern to
4577# match it with.
4578 _PATTERNS_TO_CHECK={
4579'content::GetServiceSandboxType<>()':'GetServiceSandboxType\\<'
4580}
4581 _PATTERNS_TO_CHECK={
4582 k: input_api.re.compile(v)
4583for k, vin _PATTERNS_TO_CHECK.items()
4584}
4585
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4586# We don't want to trigger on strings within this file.
4587def presubmit_file_filter(f):
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4588return'PRESUBMIT.py'!= input_api.os_path.split(f.LocalPath())[1]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4589
4590# Scan all affected files for changes touching _FUNCTIONS_TO_CHECK.
4591 files_to_functions={}
4592for fin input_api.AffectedFiles(file_filter=presubmit_file_filter):
4593 diff= f.GenerateScmDiff()
4594for linein diff.split('\n'):
4595# Not using just RightHandSideLines() because removing a
4596# call to a security-critical function can be just as important
4597# as adding or changing the arguments.
4598if line.startswith('-')or(line.startswith('+')
4599andnot line.startswith('++')):
4600for name, patternin _PATTERNS_TO_CHECK.items():
4601if pattern.search(line):
4602 path= f.LocalPath()
4603ifnot pathin files_to_functions:
4604 files_to_functions[path]= set()
4605 files_to_functions[path].add(name)
4606return files_to_functions
4607
4608
4609defCheckSecurityChanges(input_api, output_api):
4610"""Checks that changes involving security-critical functions are reviewed
4611 by the security team.
4612 """
4613 files_to_functions=_GetFilesUsingSecurityCriticalFunctions(input_api)
4614ifnot len(files_to_functions):
4615return[]
4616
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4617 owners_file='ipc/SECURITY_OWNERS'
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4618if_ChangeHasSecurityReviewer(input_api, owners_file):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4619return[]
4620
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]4621 msg='The following files change calls to security-sensitive functions\n' \
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4622'that need to be reviewed by {}.\n'.format(owners_file)
4623for path, namesin files_to_functions.items():
4624 msg+=' {}\n'.format(path)
4625for namein names:
4626 msg+=' {}\n'.format(name)
4627 msg+='\n'
4628
4629if input_api.is_committing:
4630 output= output_api.PresubmitError
Mohamed Heikale217fc852020-07-06 19:44:03[diff] [blame]4631else:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4632 output= output_api.PresubmitNotifyResult
4633return[output(msg)]
4634
4635
4636defCheckSetNoParent(input_api, output_api):
4637"""Checks that set noparent is only used together with an OWNERS file in
4638 //build/OWNERS.setnoparent (see also
4639 //docs/code_reviews.md#owners-files-details)
4640 """
4641# Return early if no OWNERS files were modified.
4642ifnot any(f.LocalPath().endswith('OWNERS')
4643for fin input_api.AffectedFiles(include_deletes=False)):
4644return[]
4645
4646 errors=[]
4647
4648 allowed_owners_files_file='build/OWNERS.setnoparent'
4649 allowed_owners_files= set()
Bruce Dawson58a45d22023-02-27 11:24:16[diff] [blame]4650with open(allowed_owners_files_file,'r', encoding='utf-8')as f:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4651for linein f:
4652 line= line.strip()
4653ifnot lineor line.startswith('#'):
4654continue
4655 allowed_owners_files.add(line)
4656
4657 per_file_pattern= input_api.re.compile('per-file (.+)=(.+)')
4658
4659for fin input_api.AffectedFiles(include_deletes=False):
4660ifnot f.LocalPath().endswith('OWNERS'):
4661continue
4662
4663 found_owners_files= set()
4664 found_set_noparent_lines= dict()
4665
4666# Parse the OWNERS file.
4667for lineno, linein enumerate(f.NewContents(),1):
4668 line= line.strip()
4669if line.startswith('set noparent'):
4670 found_set_noparent_lines['']= lineno
4671if line.startswith('file://'):
4672if linein allowed_owners_files:
4673 found_owners_files.add('')
4674if line.startswith('per-file'):
4675 match= per_file_pattern.match(line)
4676if match:
4677 glob= match.group(1).strip()
4678 directive= match.group(2).strip()
4679if directive=='set noparent':
4680 found_set_noparent_lines[glob]= lineno
4681if directive.startswith('file://'):
4682if directivein allowed_owners_files:
4683 found_owners_files.add(glob)
4684
4685# Check that every set noparent line has a corresponding file:// line
4686# listed in build/OWNERS.setnoparent. An exception is made for top level
4687# directories since src/OWNERS shouldn't review them.
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]4688 linux_path= f.UnixLocalPath()
Bruce Dawson6bb0d672022-04-06 15:13:49[diff] [blame]4689if(linux_path.count('/')!=1
4690and(not linux_pathin _EXCLUDED_SET_NO_PARENT_PATHS)):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4691for set_noparent_linein found_set_noparent_lines:
4692if set_noparent_linein found_owners_files:
4693continue
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4694 errors.append(
4695' %s:%d'%
4696(linux_path, found_set_noparent_lines[set_noparent_line]))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4697
4698 results=[]
4699if errors:
4700if input_api.is_committing:
4701 output= output_api.PresubmitError
4702else:
4703 output= output_api.PresubmitPromptWarning
4704 results.append(
4705 output(
4706'Found the following "set noparent" restrictions in OWNERS files that '
4707'do not include owners from build/OWNERS.setnoparent:',
4708 long_text='\n\n'.join(errors)))
4709return results
4710
4711
4712defCheckUselessForwardDeclarations(input_api, output_api):
4713"""Checks that added or removed lines in non third party affected
4714 header files do not lead to new useless class or struct forward
4715 declaration.
4716 """
4717 results=[]
4718 class_pattern= input_api.re.compile(r'^class\s+(\w+);$',
4719 input_api.re.MULTILINE)
4720 struct_pattern= input_api.re.compile(r'^struct\s+(\w+);$',
4721 input_api.re.MULTILINE)
4722for fin input_api.AffectedFiles(include_deletes=False):
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]4723 local_path= f.UnixLocalPath()
4724if(local_path.startswith('third_party')
4725andnot local_path.startswith('third_party/blink')):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4726continue
4727
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]4728ifnot local_path.endswith('.h'):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4729continue
4730
4731 contents= input_api.ReadFile(f)
4732 fwd_decls= input_api.re.findall(class_pattern, contents)
4733 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
4734
4735 useless_fwd_decls=[]
4736for declin fwd_decls:
4737 count= sum(1for _in input_api.re.finditer(
4738 r'\b%s\b'% input_api.re.escape(decl), contents))
4739if count==1:
4740 useless_fwd_decls.append(decl)
4741
4742ifnot useless_fwd_decls:
4743continue
4744
4745for linein f.GenerateScmDiff().splitlines():
4746if(line.startswith('-')andnot line.startswith('--')
4747or line.startswith('+')andnot line.startswith('++')):
4748for declin useless_fwd_decls:
4749if input_api.re.search(r'\b%s\b'% decl, line[1:]):
4750 results.append(
4751 output_api.PresubmitPromptWarning(
4752'%s: %s forward declaration is no longer needed'
4753%(f.LocalPath(), decl)))
4754 useless_fwd_decls.remove(decl)
4755
4756return results
4757
4758
4759def_CheckAndroidDebuggableBuild(input_api, output_api):
4760"""Checks that code uses BuildInfo.isDebugAndroid() instead of
4761 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
4762 this is a debuggable build of Android.
4763 """
4764 build_type_check_pattern= input_api.re.compile(
4765 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
4766
4767 errors=[]
4768
4769 sources=lambda affected_file: input_api.FilterSourceFile(
4770 affected_file,
4771 files_to_skip=(
4772 _EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+ input_api.
4773 DEFAULT_FILES_TO_SKIP+(
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4774 r"^android_webview/support_library/boundary_interfaces/",
4775 r"^chrome/android/webapk/.*",
4776 r'^third_party/.*',
4777 r"tools/android/customtabs_benchmark/.*",
4778 r"webview/chromium/License.*",
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4779)),
4780 files_to_check=[r'.*\.java$'])
4781
4782for fin input_api.AffectedSourceFiles(sources):
4783for line_num, linein f.ChangedContents():
4784if build_type_check_pattern.search(line):
4785 errors.append("%s:%d"%(f.LocalPath(), line_num))
4786
4787 results=[]
4788
4789if errors:
4790 results.append(
4791 output_api.PresubmitPromptWarning(
4792'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
4793' Please use BuildInfo.isDebugAndroid() instead.', errors))
4794
4795return results
4796
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4797
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4798# TODO: add unit tests
4799def_CheckAndroidToastUsage(input_api, output_api):
4800"""Checks that code uses org.chromium.ui.widget.Toast instead of
4801 android.widget.Toast (Chromium Toast doesn't force hardware
4802 acceleration on low-end devices, saving memory).
4803 """
4804 toast_import_pattern= input_api.re.compile(
4805 r'^import android\.widget\.Toast;$')
4806
4807 errors=[]
4808
4809 sources=lambda affected_file: input_api.FilterSourceFile(
4810 affected_file,
4811 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+ input_api.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4812 DEFAULT_FILES_TO_SKIP+
4813(r'^chromecast/.*', r'^remoting/.*')),
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4814 files_to_check=[r'.*\.java$'])
4815
4816for fin input_api.AffectedSourceFiles(sources):
4817for line_num, linein f.ChangedContents():
4818if toast_import_pattern.search(line):
4819 errors.append("%s:%d"%(f.LocalPath(), line_num))
4820
4821 results=[]
4822
4823if errors:
4824 results.append(
4825 output_api.PresubmitError(
4826'android.widget.Toast usage is detected. Android toasts use hardware'
4827' acceleration, and can be\ncostly on low-end devices. Please use'
4828' org.chromium.ui.widget.Toast instead.\n'
4829'Contact dskiba@chromium.org if you have any questions.',
4830 errors))
4831
4832return results
4833
4834
4835def_CheckAndroidCrLogUsage(input_api, output_api):
4836"""Checks that new logs using org.chromium.base.Log:
4837 - Are using 'TAG' as variable name for the tags (warn)
4838 - Are using a tag that is shorter than 20 characters (error)
4839 """
4840
4841# Do not check format of logs in the given files
4842 cr_log_check_excluded_paths=[
4843# //chrome/android/webapk cannot depend on //base
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4844 r"^chrome/android/webapk/.*",
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4845# WebView license viewer code cannot depend on //base; used in stub APK.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4846 r"^android_webview/glue/java/src/com/android/"
4847 r"webview/chromium/License.*",
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4848# The customtabs_benchmark is a small app that does not depend on Chromium
4849# java pieces.
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]4850 r"tools/android/customtabs_benchmark/.*",
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4851]
4852
4853 cr_log_import_pattern= input_api.re.compile(
4854 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
4855 class_in_base_pattern= input_api.re.compile(
4856 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
4857 has_some_log_import_pattern= input_api.re.compile(r'^import .*\.Log;$',
4858 input_api.re.MULTILINE)
4859# Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
4860 log_call_pattern= input_api.re.compile(r'\bLog\.\w\((?P<tag>\"?\w+)')
4861 log_decl_pattern= input_api.re.compile(
4862 r'static final String TAG = "(?P<name>(.*))"')
4863 rough_log_decl_pattern= input_api.re.compile(r'\bString TAG\s*=')
4864
4865 REF_MSG=('See docs/android_logging.md for more info.')
4866 sources=lambda x: input_api.FilterSourceFile(
4867 x,
4868 files_to_check=[r'.*\.java$'],
4869 files_to_skip=cr_log_check_excluded_paths)
4870
4871 tag_decl_errors=[]
Andrew Grieved3a35d82024-01-02 21:24:38[diff] [blame]4872 tag_length_errors=[]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4873 tag_errors=[]
4874 tag_with_dot_errors=[]
4875 util_log_errors=[]
4876
4877for fin input_api.AffectedSourceFiles(sources):
4878 file_content= input_api.ReadFile(f)
4879 has_modified_logs=False
4880# Per line checks
4881if(cr_log_import_pattern.search(file_content)
4882or(class_in_base_pattern.search(file_content)
4883andnot has_some_log_import_pattern.search(file_content))):
4884# Checks to run for files using cr log
4885for line_num, linein f.ChangedContents():
4886if rough_log_decl_pattern.search(line):
4887 has_modified_logs=True
4888
4889# Check if the new line is doing some logging
4890 match= log_call_pattern.search(line)
4891if match:
4892 has_modified_logs=True
4893
4894# Make sure it uses "TAG"
4895ifnot match.group('tag')=='TAG':
4896 tag_errors.append("%s:%d"%(f.LocalPath(), line_num))
4897else:
4898# Report non cr Log function calls in changed lines
4899for line_num, linein f.ChangedContents():
4900if log_call_pattern.search(line):
4901 util_log_errors.append("%s:%d"%(f.LocalPath(), line_num))
4902
4903# Per file checks
4904if has_modified_logs:
4905# Make sure the tag is using the "cr" prefix and is not too long
4906 match= log_decl_pattern.search(file_content)
4907 tag_name= match.group('name')if matchelseNone
4908ifnot tag_name:
4909 tag_decl_errors.append(f.LocalPath())
Andrew Grieved3a35d82024-01-02 21:24:38[diff] [blame]4910elif len(tag_name)>20:
4911 tag_length_errors.append(f.LocalPath())
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4912elif'.'in tag_name:
4913 tag_with_dot_errors.append(f.LocalPath())
4914
4915 results=[]
4916if tag_decl_errors:
4917 results.append(
4918 output_api.PresubmitPromptWarning(
4919'Please define your tags using the suggested format: .\n'
4920'"private static final String TAG = "<package tag>".\n'
4921'They will be prepended with "cr_" automatically.\n'+ REF_MSG,
4922 tag_decl_errors))
4923
Andrew Grieved3a35d82024-01-02 21:24:38[diff] [blame]4924if tag_length_errors:
4925 results.append(
4926 output_api.PresubmitError(
4927'The tag length is restricted by the system to be at most '
4928'20 characters.\n'+ REF_MSG, tag_length_errors))
4929
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4930if tag_errors:
4931 results.append(
4932 output_api.PresubmitPromptWarning(
4933'Please use a variable named "TAG" for your log tags.\n'+
4934 REF_MSG, tag_errors))
4935
4936if util_log_errors:
4937 results.append(
4938 output_api.PresubmitPromptWarning(
4939'Please use org.chromium.base.Log for new logs.\n'+ REF_MSG,
4940 util_log_errors))
4941
4942if tag_with_dot_errors:
4943 results.append(
4944 output_api.PresubmitPromptWarning(
4945'Dot in log tags cause them to be elided in crash reports.\n'+
4946 REF_MSG, tag_with_dot_errors))
4947
4948return results
4949
4950
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4951def_CheckAndroidTestAnnotationUsage(input_api, output_api):
4952"""Checks that android.test.suitebuilder.annotation.* is no longer used."""
4953 deprecated_annotation_import_pattern= input_api.re.compile(
4954 r'^import android\.test\.suitebuilder\.annotation\..*;',
4955 input_api.re.MULTILINE)
4956 sources=lambda x: input_api.FilterSourceFile(
4957 x, files_to_check=[r'.*\.java$'], files_to_skip=None)
4958 errors=[]
4959for fin input_api.AffectedFiles(file_filter=sources):
4960for line_num, linein f.ChangedContents():
4961if deprecated_annotation_import_pattern.search(line):
4962 errors.append("%s:%d"%(f.LocalPath(), line_num))
4963
4964 results=[]
4965if errors:
4966 results.append(
4967 output_api.PresubmitError(
4968'Annotations in android.test.suitebuilder.annotation have been'
Mohamed Heikal3d7a94c2023-03-28 16:55:24[diff] [blame]4969' deprecated since API level 24. Please use androidx.test.filters'
4970' from //third_party/androidx:androidx_test_runner_java instead.'
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4971' Contact yolandyan@chromium.org if you have any questions.',
4972 errors))
4973return results
4974
4975
4976def_CheckAndroidNewMdpiAssetLocation(input_api, output_api):
4977"""Checks if MDPI assets are placed in a correct directory."""
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]4978 file_filter=lambda f:(f.UnixLocalPath().endswith('.png')and
4979('/res/drawable/'in f.UnixLocalPath()or
4980'/res/drawable-ldrtl/'in f.UnixLocalPath()))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]4981 errors=[]
4982for fin input_api.AffectedFiles(include_deletes=False,
4983 file_filter=file_filter):
4984 errors.append(' %s'% f.LocalPath())
4985
4986 results=[]
4987if errors:
4988 results.append(
4989 output_api.PresubmitError(
4990'MDPI assets should be placed in /res/drawable-mdpi/ or '
4991'/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
4992'/res/drawable-ldrtl/.\n'
4993'Contact newt@chromium.org if you have questions.', errors))
4994return results
4995
4996
4997def_CheckAndroidWebkitImports(input_api, output_api):
4998"""Checks that code uses org.chromium.base.Callback instead of
4999 android.webview.ValueCallback except in the WebView glue layer
5000 and WebLayer.
5001 """
5002 valuecallback_import_pattern= input_api.re.compile(
5003 r'^import android\.webkit\.ValueCallback;$')
5004
5005 errors=[]
5006
5007 sources=lambda affected_file: input_api.FilterSourceFile(
5008 affected_file,
5009 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+ input_api.
5010 DEFAULT_FILES_TO_SKIP+(
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]5011 r'^android_webview/glue/.*',
elabadysayedcbbaea72024-08-01 16:10:42[diff] [blame]5012 r'^android_webview/support_library/.*',
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]5013 r'^weblayer/.*',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5014)),
5015 files_to_check=[r'.*\.java$'])
5016
5017for fin input_api.AffectedSourceFiles(sources):
5018for line_num, linein f.ChangedContents():
5019if valuecallback_import_pattern.search(line):
5020 errors.append("%s:%d"%(f.LocalPath(), line_num))
5021
5022 results=[]
5023
5024if errors:
5025 results.append(
5026 output_api.PresubmitError(
5027'android.webkit.ValueCallback usage is detected outside of the glue'
5028' layer. To stay compatible with the support library, android.webkit.*'
5029' classes should only be used inside the glue layer and'
5030' org.chromium.base.Callback should be used instead.', errors))
5031
5032return results
5033
5034
5035def_CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
5036"""Checks Android XML styles """
5037
5038# Return early if no relevant files were modified.
5039ifnot any(
5040_IsXmlOrGrdFile(input_api, f.LocalPath())
5041for fin input_api.AffectedFiles(include_deletes=False)):
5042return[]
5043
5044import sys
5045 original_sys_path= sys.path
5046try:
5047 sys.path= sys.path+[
5048 input_api.os_path.join(input_api.PresubmitLocalPath(),'tools',
5049'android','checkxmlstyle')
5050]
5051import checkxmlstyle
5052finally:
5053# Restore sys.path to what it was before.
5054 sys.path= original_sys_path
5055
5056if is_check_on_upload:
5057return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
5058else:
5059return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
5060
5061
5062def_CheckAndroidInfoBarDeprecation(input_api, output_api):
5063"""Checks Android Infobar Deprecation """
5064
5065import sys
5066 original_sys_path= sys.path
5067try:
5068 sys.path= sys.path+[
5069 input_api.os_path.join(input_api.PresubmitLocalPath(),'tools',
5070'android','infobar_deprecation')
5071]
5072import infobar_deprecation
5073finally:
5074# Restore sys.path to what it was before.
5075 sys.path= original_sys_path
5076
5077return infobar_deprecation.CheckDeprecationOnUpload(input_api, output_api)
5078
5079
5080class_PydepsCheckerResult:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5081
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5082def __init__(self, cmd, pydeps_path, process, old_contents):
5083 self._cmd= cmd
5084 self._pydeps_path= pydeps_path
5085 self._process= process
5086 self._old_contents= old_contents
5087
5088defGetError(self):
5089"""Returns an error message, or None."""
5090import difflib
Andrew Grieved27620b62023-07-13 16:35:07[diff] [blame]5091 new_contents= self._process.stdout.read().splitlines()[2:]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5092if self._process.wait()!=0:
5093# STDERR should already be printed.
5094return'Command failed: '+ self._cmd
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5095if self._old_contents!= new_contents:
5096 diff='\n'.join(
5097 difflib.context_diff(self._old_contents, new_contents))
5098return('File is stale: {}\n'
5099'Diff (apply to fix):\n'
5100'{}\n'
5101'To regenerate, run:\n\n'
5102' {}').format(self._pydeps_path, diff, self._cmd)
5103returnNone
5104
5105
5106classPydepsChecker:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5107
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5108def __init__(self, input_api, pydeps_files):
5109 self._file_cache={}
5110 self._input_api= input_api
5111 self._pydeps_files= pydeps_files
5112
5113def_LoadFile(self, path):
5114"""Returns the list of paths within a .pydeps file relative to //."""
5115if pathnotin self._file_cache:
5116with open(path, encoding='utf-8')as f:
5117 self._file_cache[path]= f.read()
5118return self._file_cache[path]
5119
5120def_ComputeNormalizedPydepsEntries(self, pydeps_path):
Gao Shenga79ebd42022-08-08 17:25:59[diff] [blame]5121"""Returns an iterable of paths within the .pydep, relativized to //."""
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5122 pydeps_data= self._LoadFile(pydeps_path)
5123 uses_gn_paths='--gn-paths'in pydeps_data
5124 entries=(lfor lin pydeps_data.splitlines()
5125ifnot l.startswith('#'))
5126if uses_gn_paths:
5127# Paths look like: //foo/bar/baz
5128return(e[2:]for ein entries)
5129else:
5130# Paths look like: path/relative/to/file.pydeps
5131 os_path= self._input_api.os_path
5132 pydeps_dir= os_path.dirname(pydeps_path)
5133return(os_path.normpath(os_path.join(pydeps_dir, e))
5134for ein entries)
5135
5136def_CreateFilesToPydepsMap(self):
5137"""Returns a map of local_path -> list_of_pydeps."""
5138 ret={}
5139for pydep_local_pathin self._pydeps_files:
5140for pathin self._ComputeNormalizedPydepsEntries(pydep_local_path):
5141 ret.setdefault(path,[]).append(pydep_local_path)
5142return ret
5143
5144defComputeAffectedPydeps(self):
5145"""Returns an iterable of .pydeps files that might need regenerating."""
5146 affected_pydeps= set()
5147 file_to_pydeps_map=None
5148for fin self._input_api.AffectedFiles(include_deletes=True):
5149 local_path= f.LocalPath()
5150# Changes to DEPS can lead to .pydeps changes if any .py files are in
5151# subrepositories. We can't figure out which files change, so re-check
5152# all files.
5153# Changes to print_python_deps.py affect all .pydeps.
5154if local_pathin('DEPS','PRESUBMIT.py'
5155)or local_path.endswith('print_python_deps.py'):
5156return self._pydeps_files
5157elif local_path.endswith('.pydeps'):
5158if local_pathin self._pydeps_files:
5159 affected_pydeps.add(local_path)
5160elif local_path.endswith('.py'):
5161if file_to_pydeps_mapisNone:
5162 file_to_pydeps_map= self._CreateFilesToPydepsMap()
5163 affected_pydeps.update(file_to_pydeps_map.get(local_path,()))
5164return affected_pydeps
5165
5166defDetermineIfStaleAsync(self, pydeps_path):
5167"""Runs print_python_deps.py to see if the files is stale."""
5168import os
5169
5170 old_pydeps_data= self._LoadFile(pydeps_path).splitlines()
5171if old_pydeps_data:
5172 cmd= old_pydeps_data[1][1:].strip()
5173if'--output'notin cmd:
5174 cmd+=' --output '+ pydeps_path
5175 old_contents= old_pydeps_data[2:]
5176else:
5177# A default cmd that should work in most cases (as long as pydeps filename
5178# matches the script name) so that PRESUBMIT.py does not crash if pydeps
5179# file is empty/new.
5180 cmd='build/print_python_deps.py {} --root={} --output={}'.format(
5181 pydeps_path[:-4], os.path.dirname(pydeps_path), pydeps_path)
5182 old_contents=[]
5183 env= dict(os.environ)
5184 env['PYTHONDONTWRITEBYTECODE']='1'
5185 process= self._input_api.subprocess.Popen(
5186 cmd+' --output ""',
5187 shell=True,
5188 env=env,
5189 stdout=self._input_api.subprocess.PIPE,
5190 encoding='utf-8')
5191return_PydepsCheckerResult(cmd, pydeps_path, process, old_contents)
agrievef32bcc72016-04-04 14:57:40[diff] [blame]5192
5193
Tibor Goldschwendt360793f72019-06-25 18:23:49[diff] [blame]5194def_ParseGclientArgs():
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5195 args={}
5196with open('build/config/gclient_args.gni','r')as f:
5197for linein f:
5198 line= line.strip()
5199ifnot lineor line.startswith('#'):
5200continue
5201 attribute, value= line.split('=')
5202 args[attribute.strip()]= value.strip()
5203return args
Tibor Goldschwendt360793f72019-06-25 18:23:49[diff] [blame]5204
5205
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5206defCheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5207"""Checks if a .pydeps file needs to be regenerated."""
5208# This check is for Python dependency lists (.pydeps files), and involves
5209# paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
5210# doesn't work on Windows and Mac, so skip it on other platforms.
5211ifnot input_api.platform.startswith('linux'):
5212return[]
Erik Staabc734cd7a2021-11-23 03:11:52[diff] [blame]5213
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5214 results=[]
5215# First, check for new / deleted .pydeps.
5216for fin input_api.AffectedFiles(include_deletes=True):
5217# Check whether we are running the presubmit check for a file in src.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5218if f.LocalPath().endswith('.pydeps'):
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]5219# f.LocalPath is relative to repo (src, or internal repo).
5220# os_path.exists is relative to src repo.
5221# Therefore if os_path.exists is true, it means f.LocalPath is relative
5222# to src and we can conclude that the pydeps is in src.
5223 exists= input_api.os_path.exists(f.LocalPath())
5224if f.Action()=='D'and f.LocalPath()in _ALL_PYDEPS_FILES:
5225 results.append(
5226 output_api.PresubmitError(
5227'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
5228'remove %s'% f.LocalPath()))
5229elif(f.Action()!='D'and exists
5230and f.LocalPath()notin _ALL_PYDEPS_FILES):
5231 results.append(
5232 output_api.PresubmitError(
5233'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
5234'include %s'% f.LocalPath()))
agrievef32bcc72016-04-04 14:57:40[diff] [blame]5235
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5236if results:
5237return results
5238
Gavin Mak23884402024-07-25 20:39:26[diff] [blame]5239try:
5240 parsed_args=_ParseGclientArgs()
5241exceptFileNotFoundError:
5242 message=(
5243'build/config/gclient_args.gni not found. Please make sure your '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5244'workspace has been initialized with gclient sync.')
Gavin Mak23884402024-07-25 20:39:26[diff] [blame]5245import sys
5246 original_sys_path= sys.path
5247try:
5248 sys.path= sys.path+[
5249 input_api.os_path.join(input_api.PresubmitLocalPath(),
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5250'third_party','depot_tools')
Gavin Mak23884402024-07-25 20:39:26[diff] [blame]5251]
5252import gclient_utils
5253if gclient_utils.IsEnvCog():
5254# Users will always hit this when they run presubmits before cog
5255# workspace initialization finishes. The check shouldn't fail in
5256# this case. This is an unavoidable workaround that's needed for
5257# good presubmit UX for cog.
5258 results.append(output_api.PresubmitPromptWarning(message))
5259else:
5260 results.append(output_api.PresubmitError(message))
5261return results
5262finally:
5263# Restore sys.path to what it was before.
5264 sys.path= original_sys_path
5265
5266 is_android= parsed_args.get('checkout_android','false')=='true'
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5267 checker= checker_for_testsorPydepsChecker(input_api, _ALL_PYDEPS_FILES)
5268 affected_pydeps= set(checker.ComputeAffectedPydeps())
5269 affected_android_pydeps= affected_pydeps.intersection(
5270 set(_ANDROID_SPECIFIC_PYDEPS_FILES))
5271if affected_android_pydepsandnot is_android:
5272 results.append(
5273 output_api.PresubmitPromptOrNotify(
5274'You have changed python files that may affect pydeps for android\n'
Gao Shenga79ebd42022-08-08 17:25:59[diff] [blame]5275'specific scripts. However, the relevant presubmit check cannot be\n'
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5276'run because you are not using an Android checkout. To validate that\n'
5277'the .pydeps are correct, re-run presubmit in an Android checkout, or\n'
5278'use the android-internal-presubmit optional trybot.\n'
5279'Possibly stale pydeps files:\n{}'.format(
5280'\n'.join(affected_android_pydeps))))
5281
5282 all_pydeps= _ALL_PYDEPS_FILESif is_androidelse _GENERIC_PYDEPS_FILES
5283 pydeps_to_check= affected_pydeps.intersection(all_pydeps)
5284# Process these concurrently, as each one takes 1-2 seconds.
5285 pydep_results=[checker.DetermineIfStaleAsync(p)for pin pydeps_to_check]
5286for resultin pydep_results:
5287 error_msg= result.GetError()
5288if error_msg:
5289 results.append(output_api.PresubmitError(error_msg))
5290
agrievef32bcc72016-04-04 14:57:40[diff] [blame]5291return results
5292
agrievef32bcc72016-04-04 14:57:40[diff] [blame]5293
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5294defCheckSingletonInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5295"""Checks to make sure no header files have |Singleton<|."""
5296
5297defFileFilter(affected_file):
5298# It's ok for base/memory/singleton.h to have |Singleton<|.
5299 files_to_skip=(_EXCLUDED_PATHS+ input_api.DEFAULT_FILES_TO_SKIP+
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]5300(r"^base/memory/singleton\.h$",
5301 r"^net/quic/platform/impl/quic_singleton_impl\.h$"))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5302return input_api.FilterSourceFile(affected_file,
5303 files_to_skip=files_to_skip)
glidere61efad2015-02-18 17:39:43[diff] [blame]5304
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5305 pattern= input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
5306 files=[]
5307for fin input_api.AffectedSourceFiles(FileFilter):
5308if(f.LocalPath().endswith('.h')or f.LocalPath().endswith('.hxx')
5309or f.LocalPath().endswith('.hpp')
5310or f.LocalPath().endswith('.inl')):
5311 contents= input_api.ReadFile(f)
5312for linein contents.splitlines(False):
5313if(not line.lstrip().startswith('//')
5314and# Strip C++ comment.
5315 pattern.search(line)):
5316 files.append(f)
5317break
glidere61efad2015-02-18 17:39:43[diff] [blame]5318
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5319if files:
5320return[
5321 output_api.PresubmitError(
5322'Found base::Singleton<T> in the following header files.\n'+
5323'Please move them to an appropriate source file so that the '+
5324'template gets instantiated in a single compilation unit.',
5325 files)
5326]
5327return[]
glidere61efad2015-02-18 17:39:43[diff] [blame]5328
5329
jchaffraix@chromium.orgfd20b902014-05-09 02:14:53[diff] [blame]5330_DEPRECATED_CSS=[
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5331# Values
5332("-webkit-box","flex"),
5333("-webkit-inline-box","inline-flex"),
5334("-webkit-flex","flex"),
5335("-webkit-inline-flex","inline-flex"),
5336("-webkit-min-content","min-content"),
5337("-webkit-max-content","max-content"),
jchaffraix@chromium.orgfd20b902014-05-09 02:14:53[diff] [blame]5338
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5339# Properties
5340("-webkit-background-clip","background-clip"),
5341("-webkit-background-origin","background-origin"),
5342("-webkit-background-size","background-size"),
5343("-webkit-box-shadow","box-shadow"),
5344("-webkit-user-select","user-select"),
jchaffraix@chromium.orgfd20b902014-05-09 02:14:53[diff] [blame]5345
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5346# Functions
5347("-webkit-gradient","gradient"),
5348("-webkit-repeating-gradient","repeating-gradient"),
5349("-webkit-linear-gradient","linear-gradient"),
5350("-webkit-repeating-linear-gradient","repeating-linear-gradient"),
5351("-webkit-radial-gradient","radial-gradient"),
5352("-webkit-repeating-radial-gradient","repeating-radial-gradient"),
jchaffraix@chromium.orgfd20b902014-05-09 02:14:53[diff] [blame]5353]
5354
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:20[diff] [blame]5355
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:49[diff] [blame]5356# TODO: add unit tests
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5357defCheckNoDeprecatedCss(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5358""" Make sure that we don't use deprecated CSS
5359 properties, functions or values. Our external
5360 documentation and iOS CSS for dom distiller
5361 (reader mode) are ignored by the hooks as it
5362 needs to be consumed by WebKit. """
5363 results=[]
5364 file_inclusion_pattern=[r".+\.css$"]
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5365 files_to_skip=(
5366 _EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
5367 input_api.DEFAULT_FILES_TO_SKIP+
5368(# Legacy CSS file using deprecated CSS.
5369 r"^chrome/browser/resources/chromeos/arc_support/cr_overlay.css$",
5370 r"^chrome/common/extensions/docs",
5371 r"^chrome/docs",
5372 r"^native_client_sdk",
5373# The NTP team prefers reserving -webkit-line-clamp for
5374# ellipsis effect which can only be used with -webkit-box.
5375 r"ui/webui/resources/cr_components/most_visited/.*\.css$"))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5376 file_filter=lambda f: input_api.FilterSourceFile(
5377 f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
5378for fpathin input_api.AffectedFiles(file_filter=file_filter):
5379for line_num, linein fpath.ChangedContents():
5380for(deprecated_value, value)in _DEPRECATED_CSS:
5381if deprecated_valuein line:
5382 results.append(
5383 output_api.PresubmitError(
5384"%s:%d: Use of deprecated CSS %s, use %s instead"%
5385(fpath.LocalPath(), line_num, deprecated_value,
5386 value)))
5387return results
jchaffraix@chromium.orgfd20b902014-05-09 02:14:53[diff] [blame]5388
mohan.reddyf21db962014-10-16 12:26:47[diff] [blame]5389
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5390defCheckForRelativeIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5391 bad_files={}
5392for fin input_api.AffectedFiles(include_deletes=False):
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]5393if(f.UnixLocalPath().startswith('third_party')
5394andnot f.LocalPath().startswith('third_party/blink')):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5395continue
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5396
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5397ifnot_IsCPlusPlusFile(input_api, f.LocalPath()):
5398continue
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5399
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5400 relative_includes=[
5401 linefor _, linein f.ChangedContents()
5402if"#include"in lineand"../"in line
5403]
5404ifnot relative_includes:
5405continue
5406 bad_files[f.LocalPath()]= relative_includes
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5407
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5408ifnot bad_files:
5409return[]
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5410
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5411 error_descriptions=[]
5412for file_path, bad_linesin bad_files.items():
5413 error_description= file_path
5414for linein bad_lines:
5415 error_description+='\n '+ line
5416 error_descriptions.append(error_description)
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5417
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5418 results=[]
5419 results.append(
5420 output_api.PresubmitError(
5421'You added one or more relative #include paths (including "../").\n'
5422'These shouldn\'t be used because they can be used to include headers\n'
5423'from code that\'s not correctly specified as a dependency in the\n'
5424'relevant BUILD.gn file(s).', error_descriptions))
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5425
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5426return results
rlanday6802cf632017-05-30 17:48:36[diff] [blame]5427
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5428
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5429defCheckForCcIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5430"""Check that nobody tries to include a cc file. It's a relatively
5431 common error which results in duplicate symbols in object
5432 files. This may not always break the build until someone later gets
5433 very confusing linking errors."""
5434 results=[]
5435for fin input_api.AffectedFiles(include_deletes=False):
5436# We let third_party code do whatever it wants
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]5437if(f.UnixLocalPath().startswith('third_party')
5438andnot f.LocalPath().startswith('third_party/blink')):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5439continue
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]5440
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5441ifnot_IsCPlusPlusFile(input_api, f.LocalPath()):
5442continue
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]5443
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5444for _, linein f.ChangedContents():
5445if line.startswith('#include "'):
5446 included_file= line.split('"')[1]
5447if_IsCPlusPlusFile(input_api, included_file):
5448# The most common naming for external files with C++ code,
5449# apart from standard headers, is to call them foo.inc, but
5450# Chromium sometimes uses foo-inc.cc so allow that as well.
5451ifnot included_file.endswith(('.h','-inc.cc')):
5452 results.append(
5453 output_api.PresubmitError(
5454'Only header files or .inc files should be included in other\n'
5455'C++ files. Compiling the contents of a cc file more than once\n'
5456'will cause duplicate information in the build which may later\n'
5457'result in strange link_errors.\n'+
5458 f.LocalPath()+':\n '+ line))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]5459
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5460return results
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]5461
5462
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5463def_CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5464ifnot isinstance(key, ast.Str):
5465return'Key at line %d must be a string literal'% key.lineno
5466ifnot isinstance(value, ast.Dict):
5467return'Value at line %d must be a dict'% value.lineno
5468if len(value.keys)!=1:
5469return'Dict at line %d must have single entry'% value.lineno
5470ifnot isinstance(value.keys[0], ast.Str)or value.keys[0].s!='filepath':
5471return(
5472'Entry at line %d must have a string literal \'filepath\' as key'%
5473 value.lineno)
5474returnNone
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5475
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5476
Sergey Ulanov4af16052018-11-08 02:41:46[diff] [blame]5477def_CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5478ifnot isinstance(key, ast.Str):
5479return'Key at line %d must be a string literal'% key.lineno
5480ifnot isinstance(value, ast.List):
5481return'Value at line %d must be a list'% value.lineno
5482for elementin value.elts:
5483ifnot isinstance(element, ast.Str):
5484return'Watchlist elements on line %d is not a string'% key.lineno
5485ifnot email_regex.match(element.s):
5486return('Watchlist element on line %d doesn\'t look like a valid '
5487+'email: %s')%(key.lineno, element.s)
5488returnNone
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5489
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5490
Sergey Ulanov4af16052018-11-08 02:41:46[diff] [blame]5491def_CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5492 mismatch_template=(
5493'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
5494'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5495
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5496 email_regex= input_api.re.compile(
5497 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
Sergey Ulanov4af16052018-11-08 02:41:46[diff] [blame]5498
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5499 ast= input_api.ast
5500 i=0
5501 last_key=''
5502whileTrue:
5503if i>= len(wd_dict.keys):
5504if i>= len(w_dict.keys):
5505returnNone
5506return mismatch_template%('missing',
5507'line %d'% w_dict.keys[i].lineno)
5508elif i>= len(w_dict.keys):
5509return(mismatch_template%
5510('line %d'% wd_dict.keys[i].lineno,'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5511
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5512 wd_key= wd_dict.keys[i]
5513 w_key= w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5514
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5515 result=_CheckWatchlistDefinitionsEntrySyntax(wd_key,
5516 wd_dict.values[i], ast)
5517if resultisnotNone:
5518return'Bad entry in WATCHLIST_DEFINITIONS dict: %s'% result
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5519
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5520 result=_CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast,
5521 email_regex)
5522if resultisnotNone:
5523return'Bad entry in WATCHLISTS dict: %s'% result
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5524
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5525if wd_key.s!= w_key.s:
5526return mismatch_template%('%s at line %d'%
5527(wd_key.s, wd_key.lineno),
5528'%s at line %d'%
5529(w_key.s, w_key.lineno))
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5530
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5531if wd_key.s< last_key:
5532return(
5533'WATCHLISTS dict is not sorted lexicographically at line %d and %d'
5534%(wd_key.lineno, w_key.lineno))
5535 last_key= wd_key.s
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5536
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5537 i= i+1
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5538
5539
Sergey Ulanov4af16052018-11-08 02:41:46[diff] [blame]5540def_CheckWATCHLISTSSyntax(expression, input_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5541 ast= input_api.ast
5542ifnot isinstance(expression, ast.Expression):
5543return'WATCHLISTS file must contain a valid expression'
5544 dictionary= expression.body
5545ifnot isinstance(dictionary, ast.Dict)or len(dictionary.keys)!=2:
5546return'WATCHLISTS file must have single dict with exactly two entries'
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5547
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5548 first_key= dictionary.keys[0]
5549 first_value= dictionary.values[0]
5550 second_key= dictionary.keys[1]
5551 second_value= dictionary.values[1]
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5552
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5553if(not isinstance(first_key, ast.Str)
5554or first_key.s!='WATCHLIST_DEFINITIONS'
5555ornot isinstance(first_value, ast.Dict)):
5556return('The first entry of the dict in WATCHLISTS file must be '
5557'WATCHLIST_DEFINITIONS dict')
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5558
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5559if(not isinstance(second_key, ast.Str)or second_key.s!='WATCHLISTS'
5560ornot isinstance(second_value, ast.Dict)):
5561return('The second entry of the dict in WATCHLISTS file must be '
5562'WATCHLISTS dict')
Takeshi Yoshino3a8f9cb52017-08-10 11:32:20[diff] [blame]5563
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5564return_CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5565
5566
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5567defCheckWATCHLISTS(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5568for fin input_api.AffectedFiles(include_deletes=False):
5569if f.LocalPath()=='WATCHLISTS':
5570 contents= input_api.ReadFile(f,'r')
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5571
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5572try:
5573# First, make sure that it can be evaluated.
5574 input_api.ast.literal_eval(contents)
5575# Get an AST tree for it and scan the tree for detailed style checking.
5576 expression= input_api.ast.parse(contents,
5577 filename='WATCHLISTS',
5578 mode='eval')
5579exceptValueErroras e:
5580return[
5581 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5582 long_text=repr(e))
5583]
5584exceptSyntaxErroras e:
5585return[
5586 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5587 long_text=repr(e))
5588]
5589exceptTypeErroras e:
5590return[
5591 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5592 long_text=repr(e))
5593]
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5594
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5595 result=_CheckWATCHLISTSSyntax(expression, input_api)
5596if resultisnotNone:
5597return[output_api.PresubmitError(result)]
5598break
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5599
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5600return[]
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5601
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5602
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]5603defCheckGnRebasePath(input_api, output_api):
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]5604"""Checks that target_gen_dir is not used with "//" in rebase_path().
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]5605
5606 Developers should use root_build_dir instead of "//" when using target_gen_dir because
5607 Chromium is sometimes built outside of the source tree.
5608 """
5609
5610def gn_files(f):
5611return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn',))
5612
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5613 rebase_path_regex= input_api.re.compile(
5614 r'rebase_path\(("\$target_gen_dir"|target_gen_dir), ("/"|"//")\)')
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]5615 problems=[]
5616for fin input_api.AffectedSourceFiles(gn_files):
5617for line_num, linein f.ChangedContents():
5618if rebase_path_regex.search(line):
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5619 problems.append('Absolute path in rebase_path() in %s:%d'%
5620(f.LocalPath(), line_num))
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]5621
5622if problems:
5623return[
5624 output_api.PresubmitPromptWarning(
5625'Using an absolute path in rebase_path()',
5626 items=sorted(problems),
5627 long_text=(
5628'rebase_path() should use root_build_dir instead of "/" ',
5629'since builds can be initiated from outside of the source ',
5630'root.'))
5631]
5632return[]
Takeshi Yoshinoe387aa32017-08-02 13:16:13[diff] [blame]5633
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5634
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]5635defCheckGnGlobForward(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5636"""Checks that forward_variables_from(invoker, "*") follows best practices.
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]5637
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5638 As documented at //build/docs/writing_gn_templates.md
5639 """
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]5640
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5641def gn_files(f):
5642return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gni',))
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]5643
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5644 problems=[]
5645for fin input_api.AffectedSourceFiles(gn_files):
5646for line_num, linein f.ChangedContents():
5647if'forward_variables_from(invoker, "*")'in line:
5648 problems.append(
5649'Bare forward_variables_from(invoker, "*") in %s:%d'%
5650(f.LocalPath(), line_num))
5651
5652if problems:
5653return[
5654 output_api.PresubmitPromptWarning(
5655'forward_variables_from("*") without exclusions',
5656 items=sorted(problems),
5657 long_text=(
Gao Shenga79ebd42022-08-08 17:25:59[diff] [blame]5658'The variables "visibility" and "test_only" should be '
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5659'explicitly listed in forward_variables_from(). For more '
5660'details, see:\n'
5661'https://chromium.googlesource.com/chromium/src/+/HEAD/'
5662'build/docs/writing_gn_templates.md'
5663'#Using-forward_variables_from'))
5664]
5665return[]
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]5666
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5667
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5668defCheckNewHeaderWithoutGnChangeOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5669"""Checks that newly added header files have corresponding GN changes.
5670 Note that this is only a heuristic. To be precise, run script:
5671 build/check_gn_headers.py.
5672 """
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5673
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5674def headers(f):
5675return input_api.FilterSourceFile(
5676 f, files_to_check=(r'.+%s'% _HEADER_EXTENSIONS,))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5677
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5678 new_headers=[]
5679for fin input_api.AffectedSourceFiles(headers):
5680if f.Action()!='A':
5681continue
5682 new_headers.append(f.LocalPath())
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5683
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5684def gn_files(f):
5685return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn',))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5686
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5687 all_gn_changed_contents=''
5688for fin input_api.AffectedSourceFiles(gn_files):
5689for _, linein f.ChangedContents():
5690 all_gn_changed_contents+= line
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5691
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5692 problems=[]
5693for headerin new_headers:
5694 basename= input_api.os_path.basename(header)
5695if basenamenotin all_gn_changed_contents:
5696 problems.append(header)
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5697
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5698if problems:
5699return[
5700 output_api.PresubmitPromptWarning(
5701'Missing GN changes for new header files',
5702 items=sorted(problems),
5703 long_text=
5704'Please double check whether newly added header files need '
5705'corresponding changes in gn or gni files.\nThis checking is only a '
5706'heuristic. Run build/check_gn_headers.py to be precise.\n'
5707'Read https://crbug.com/661774 for more info.')
5708]
5709return[]
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]5710
5711
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5712defCheckCorrectProductNameInMessages(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5713"""Check that Chromium-branded strings don't include "Chrome" or vice versa.
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]5714
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5715 This assumes we won't intentionally reference one product from the other
5716 product.
5717 """
5718 all_problems=[]
5719 test_cases=[{
5720"filename_postfix":"google_chrome_strings.grd",
5721"correct_name":"Chrome",
5722"incorrect_name":"Chromium",
5723},{
Thiago Perrotta099034f2023-06-05 18:10:20[diff] [blame]5724"filename_postfix":"google_chrome_strings.grd",
5725"correct_name":"Chrome",
5726"incorrect_name":"Chrome for Testing",
5727},{
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5728"filename_postfix":"chromium_strings.grd",
5729"correct_name":"Chromium",
5730"incorrect_name":"Chrome",
5731}]
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]5732
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5733for test_casein test_cases:
5734 problems=[]
5735 filename_filter=lambda x: x.LocalPath().endswith(test_case[
5736"filename_postfix"])
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]5737
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5738# Check each new line. Can yield false positives in multiline comments, but
5739# easier than trying to parse the XML because messages can have nested
5740# children, and associating message elements with affected lines is hard.
5741for fin input_api.AffectedSourceFiles(filename_filter):
5742for line_num, linein f.ChangedContents():
5743if"<message"in lineor"<!--"in lineor"-->"in line:
5744continue
5745if test_case["incorrect_name"]in line:
Thiago Perrotta099034f2023-06-05 18:10:20[diff] [blame]5746# Chrome for Testing is a special edge case: https://goo.gle/chrome-for-testing#bookmark=id.n1rat320av91
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5747if(test_case["correct_name"]=="Chromium"
5748and line.count("Chrome")
5749== line.count("Chrome for Testing")):
Thiago Perrotta099034f2023-06-05 18:10:20[diff] [blame]5750continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5751 problems.append("Incorrect product name in %s:%d"%
5752(f.LocalPath(), line_num))
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]5753
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5754if problems:
5755 message=(
5756"Strings in %s-branded string files should reference \"%s\", not \"%s\""
5757%(test_case["correct_name"], test_case["correct_name"],
5758 test_case["incorrect_name"]))
5759 all_problems.append(
5760 output_api.PresubmitPromptWarning(message, items=problems))
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]5761
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5762return all_problems
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]5763
5764
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5765defCheckForTooLargeFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5766"""Avoid large files, especially binary files, in the repository since
5767 git doesn't scale well for those. They will be in everyone's repo
5768 clones forever, forever making Chromium slower to clone and work
5769 with."""
Daniel Bratell93eb6c62019-04-29 20:13:36[diff] [blame]5770
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5771# Uploading files to cloud storage is not trivial so we don't want
5772# to set the limit too low, but the upper limit for "normal" large
5773# files seems to be 1-2 MB, with a handful around 5-8 MB, so
5774# anything over 20 MB is exceptional.
Bruce Dawsonbb414db2022-12-27 20:21:25[diff] [blame]5775 TOO_LARGE_FILE_SIZE_LIMIT=20*1024*1024
Daniel Bratell93eb6c62019-04-29 20:13:36[diff] [blame]5776
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5777 too_large_files=[]
5778for fin input_api.AffectedFiles():
5779# Check both added and modified files (but not deleted files).
5780if f.Action()in('A','M'):
5781 size= input_api.os_path.getsize(f.AbsoluteLocalPath())
Joe DeBlasio10a832f2023-04-21 20:20:18[diff] [blame]5782if size> TOO_LARGE_FILE_SIZE_LIMIT:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5783 too_large_files.append("%s: %d bytes"%(f.LocalPath(), size))
Daniel Bratell93eb6c62019-04-29 20:13:36[diff] [blame]5784
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5785if too_large_files:
5786 message=(
5787'Do not commit large files to git since git scales badly for those.\n'
5788+
5789'Instead put the large files in cloud storage and use DEPS to\n'+
5790'fetch them.\n'+'\n'.join(too_large_files))
5791return[
5792 output_api.PresubmitError('Too large files found in commit',
5793 long_text=message+'\n')
5794]
5795else:
5796return[]
Daniel Bratell93eb6c62019-04-29 20:13:36[diff] [blame]5797
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5798
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5799defCheckFuzzTargetsOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5800"""Checks specific for fuzz target sources."""
5801 EXPORTED_SYMBOLS=[
5802'LLVMFuzzerInitialize',
5803'LLVMFuzzerCustomMutator',
5804'LLVMFuzzerCustomCrossOver',
5805'LLVMFuzzerMutate',
5806]
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5807
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5808 REQUIRED_HEADER='#include "testing/libfuzzer/libfuzzer_exports.h"'
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5809
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5810defFilterFile(affected_file):
5811"""Ignore libFuzzer source code."""
5812 files_to_check= r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]5813 files_to_skip= r"^third_party/libFuzzer"
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5814
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5815return input_api.FilterSourceFile(affected_file,
5816 files_to_check=[files_to_check],
5817 files_to_skip=[files_to_skip])
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5818
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5819 files_with_missing_header=[]
5820for fin input_api.AffectedSourceFiles(FilterFile):
5821 contents= input_api.ReadFile(f,'r')
5822if REQUIRED_HEADERin contents:
5823continue
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5824
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5825if any(symbolin contentsfor symbolin EXPORTED_SYMBOLS):
5826 files_with_missing_header.append(f.LocalPath())
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5827
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5828ifnot files_with_missing_header:
5829return[]
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5830
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5831 long_text=(
5832'If you define any of the libFuzzer optional functions (%s), it is '
5833'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
5834'work incorrectly on Mac (crbug.com/687076).\nNote that '
5835'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
5836'to access command line arguments passed to the fuzzer. Instead, prefer '
5837'static initialization and shared resources as documented in '
5838'https://chromium.googlesource.com/chromium/src/+/main/testing/'
5839'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n'
5840%(', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER))
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5841
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5842return[
5843 output_api.PresubmitPromptWarning(message="Missing '%s' in:"%
5844 REQUIRED_HEADER,
5845 items=files_with_missing_header,
5846 long_text=long_text)
5847]
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]5848
5849
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]5850def_CheckNewImagesWarning(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5851"""
5852 Warns authors who add images into the repo to make sure their images are
5853 optimized before committing.
5854 """
5855 images_added=False
5856 image_paths=[]
5857 errors=[]
5858 filter_lambda=lambda x: input_api.FilterSourceFile(
5859 x,
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5860 files_to_skip=(
5861('(?i).*test', r'.*\/junit\/')+ input_api.DEFAULT_FILES_TO_SKIP),
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5862 files_to_check=[r'.*\/(drawable|mipmap)'])
5863for fin input_api.AffectedFiles(include_deletes=False,
5864 file_filter=filter_lambda):
5865 local_path= f.LocalPath().lower()
5866if any(
5867 local_path.endswith(extension)
5868for extensionin _IMAGE_EXTENSIONS):
5869 images_added=True
5870 image_paths.append(f)
5871if images_added:
5872 errors.append(
5873 output_api.PresubmitPromptWarning(
5874'It looks like you are trying to commit some images. If these are '
5875'non-test-only images, please make sure to read and apply the tips in '
5876'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
5877'binary_size/optimization_advice.md#optimizing-images\nThis check is '
5878'FYI only and will not block your CL on the CQ.', image_paths))
5879return errors
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]5880
5881
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5882defChecksAndroidSpecificOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5883"""Groups upload checks that target android code."""
5884 results=[]
5885 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
5886 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
5887 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
5888 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5889 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
5890 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
5891 results.extend(_CheckAndroidXmlStyle(input_api, output_api,True))
5892 results.extend(_CheckNewImagesWarning(input_api, output_api))
5893 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
5894 results.extend(_CheckAndroidInfoBarDeprecation(input_api, output_api))
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5895 results.extend(_CheckAndroidNullAwayAnnotatedClasses(
5896 input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5897return results
5898
Becky Zhou7c69b50992018-12-10 19:37:57[diff] [blame]5899
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5900defChecksAndroidSpecificOnCommit(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5901"""Groups commit checks that target android code."""
5902 results=[]
5903 results.extend(_CheckAndroidXmlStyle(input_api, output_api,False))
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5904 results.extend(_CheckAndroidNullAwayAnnotatedClasses(
5905 input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5906return results
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]5907
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5908
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]5909# TODO(chrishall): could we additionally match on any path owned by
5910# ui/accessibility/OWNERS ?
5911_ACCESSIBILITY_PATHS=(
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]5912 r"^chrome/browser.*/accessibility/",
5913 r"^chrome/browser/extensions/api/automation.*/",
5914 r"^chrome/renderer/extensions/accessibility_.*",
5915 r"^chrome/tests/data/accessibility/",
5916 r"^content/browser/accessibility/",
5917 r"^content/renderer/accessibility/",
5918 r"^content/tests/data/accessibility/",
5919 r"^extensions/renderer/api/automation/",
Katie Dektar58ef07b2022-09-27 13:19:17[diff] [blame]5920 r"^services/accessibility/",
Abigail Klein7a63c572024-02-28 20:45:09[diff] [blame]5921 r"^services/screen_ai/",
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]5922 r"^ui/accessibility/",
5923 r"^ui/views/accessibility/",
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]5924)
5925
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5926
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]5927defCheckAccessibilityRelnotesField(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5928"""Checks that commits to accessibility code contain an AX-Relnotes field in
5929 their commit message."""
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]5930
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5931defFileFilter(affected_file):
5932 paths= _ACCESSIBILITY_PATHS
5933return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]5934
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5935# Only consider changes affecting accessibility paths.
5936ifnot any(input_api.AffectedFiles(file_filter=FileFilter)):
5937return[]
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]5938
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5939# AX-Relnotes can appear in either the description or the footer.
5940# When searching the description, require 'AX-Relnotes:' to appear at the
5941# beginning of a line.
5942 ax_regex= input_api.re.compile('ax-relnotes[:=]')
5943 description_has_relnotes= any(
5944 ax_regex.match(line)
5945for linein input_api.change.DescriptionText().lower().splitlines())
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]5946
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5947 footer_relnotes= input_api.change.GitFootersFromDescription().get(
5948'AX-Relnotes',[])
5949if description_has_relnotesor footer_relnotes:
5950return[]
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]5951
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]5952# TODO(chrishall): link to Relnotes documentation in message.
5953 message=(
5954"Missing 'AX-Relnotes:' field required for accessibility changes"
5955"\n please add 'AX-Relnotes: [release notes].' to describe any "
5956"user-facing changes"
5957"\n otherwise add 'AX-Relnotes: n/a.' if this change has no "
5958"user-facing effects"
5959"\n if this is confusing or annoying then please contact members "
5960"of ui/accessibility/OWNERS.")
5961
5962return[output_api.PresubmitNotifyResult(message)]
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]5963
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]5964
5965_ACCESSIBILITY_ARIA_METHOD_CANDIDATES_PATTERNS= r'(\-\>|\.)(get|has|FastGet|FastHas)Attribute\('
5966
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5967_ACCESSIBILITY_ARIA_BAD_PARAMS_PATTERNS=(r"\(html_names::kAria(.*)Attr\)",
5968 r"\(html_names::kRoleAttr\)")
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]5969
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5970_ACCESSIBILITY_ARIA_FILE_CANDIDATES_PATTERNS=(r".*/accessibility/.*.(cc|h)",
5971 r".*/ax_.*.(cc|h)")
5972
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]5973
5974defCheckAccessibilityAriaElementAttributeGetters(input_api, output_api):
5975"""Checks that the blink accessibility code follows the defined patterns
5976 for checking aria attributes, so that ElementInternals is not bypassed."""
5977
5978# Limit to accessibility-related files.
5979defFileFilter(affected_file):
5980 paths= _ACCESSIBILITY_ARIA_FILE_CANDIDATES_PATTERNS
5981return input_api.FilterSourceFile(affected_file, files_to_check=paths)
5982
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5983 aria_method_regex= input_api.re.compile(
5984 _ACCESSIBILITY_ARIA_METHOD_CANDIDATES_PATTERNS)
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]5985 aria_bad_params_regex= input_api.re.compile(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5986"|".join(_ACCESSIBILITY_ARIA_BAD_PARAMS_PATTERNS))
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]5987 problems=[]
5988
5989for fin input_api.AffectedSourceFiles(FileFilter):
5990for line_num, linein f.ChangedContents():
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]5991if aria_method_regex.search(line)and aria_bad_params_regex.search(
5992 line):
5993 problems.append(
5994 f"{f.LocalPath()}:{line_num}\n {line.strip()}")
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]5995
5996if problems:
5997return[
5998 output_api.PresubmitPromptWarning(
5999"Accessibility code should not use element methods to get or check"
6000"\nthe presence of aria attributes"
6001"\nPlease use ARIA-specific attribute access, e.g. HasAriaAttribute(),"
6002"\nAriaTokenAttribute(), AriaBoolAttribute(), AriaBooleanAttribute(),"
6003"\nAriaFloatAttribute().",
6004 problems,
6005)
6006]
6007return[]
6008
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6009
seanmccullough4a9356252021-04-08 19:54:09[diff] [blame]6010# string pattern, sequence of strings to show when pattern matches,
6011# error flag. True if match is a presubmit error, otherwise it's a warning.
6012_NON_INCLUSIVE_TERMS=(
6013(
6014# Note that \b pattern in python re is pretty particular. In this
6015# regexp, 'class WhiteList ...' will match, but 'class FooWhiteList
6016# ...' will not. This may require some tweaking to catch these cases
6017# without triggering a lot of false positives. Leaving it naive and
6018# less matchy for now.
Josip Sokcevic9d2806a02023-12-13 03:04:02[diff] [blame]6019 r'/(?i)\b((black|white)list|master|slave)\b',# nocheck
seanmccullough4a9356252021-04-08 19:54:09[diff] [blame]6020(
6021'Please don\'t use blacklist, whitelist, '# nocheck
6022'or slave in your',# nocheck
6023'code and make every effort to use other terms. Using "// nocheck"',
6024'"# nocheck" or "<!-- nocheck -->"',
6025'at the end of the offending line will bypass this PRESUBMIT error',
6026'but avoid using this whenever possible. Reach out to',
6027'community@chromium.org if you have questions'),
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6028True),)
6029
seanmccullough4a9356252021-04-08 19:54:09[diff] [blame]6030
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6031defChecksCommon(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6032"""Checks common to both upload and commit."""
6033 results=[]
Eric Boren6fd2b932018-01-25 15:05:08[diff] [blame]6034 results.extend(
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6035 input_api.canned_checks.PanProjectChecks(
6036 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:08[diff] [blame]6037
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6038 author= input_api.change.author_email
6039if authorand authornotin _KNOWN_ROBOTS:
6040 results.extend(
6041 input_api.canned_checks.CheckAuthorizedAuthor(
6042 input_api, output_api))
marja@chromium.org2299dcf2012-11-15 19:56:24[diff] [blame]6043
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6044 results.extend(
6045 input_api.canned_checks.CheckChangeHasNoTabs(
6046 input_api,
6047 output_api,
6048 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
6049 results.extend(
6050 input_api.RunTests(
6051 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Edward Lesmesce51df52020-08-04 22:10:17[diff] [blame]6052
Ben Pastene30dc57082025-06-02 22:19:20[diff] [blame]6053 dirmd='dirmd.bat'if input_api.is_windowselse'dirmd'
6054 dirmd_bin= input_api.os_path.join(input_api.PresubmitLocalPath(),
6055'third_party','depot_tools', dirmd)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6056 results.extend(
6057 input_api.RunTests(
6058 input_api.canned_checks.CheckDirMetadataFormat(
Ben Pastene30dc57082025-06-02 22:19:20[diff] [blame]6059 input_api, output_api, dirmd_bin)))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6060 results.extend(
6061 input_api.canned_checks.CheckOwnersDirMetadataExclusive(
6062 input_api, output_api))
6063 results.extend(
6064 input_api.canned_checks.CheckNoNewMetadataInOwners(
6065 input_api, output_api))
6066 results.extend(
6067 input_api.canned_checks.CheckInclusiveLanguage(
6068 input_api,
6069 output_api,
6070 excluded_directories_relative_path=[
6071'infra','inclusive_language_presubmit_exempt_dirs.txt'
6072],
6073 non_inclusive_terms=_NON_INCLUSIVE_TERMS))
Yiwei Zhang5341bf02025-03-20 16:34:13[diff] [blame]6074 results.extend(
6075 input_api.canned_checks.CheckNewDEPSHooksHasRequiredReviewers(
6076 input_api, output_api))
Jie Shengb0c86f02025-06-12 21:36:14[diff] [blame]6077 results.extend(
6078 input_api.canned_checks.CheckValidHostsInDEPSOnUpload(
6079 input_api, output_api))
Dirk Prankee3c9c62d2021-05-18 18:35:59[diff] [blame]6080
Aleksey Khoroshilov2978c942022-06-13 16:14:12[diff] [blame]6081 presubmit_py_filter=lambda f: input_api.FilterSourceFile(
Daniel Cheng6f3d1ae12025-04-07 17:11:27[diff] [blame]6082 f, files_to_check=[r'.*PRESUBMIT(?:_test)?\.py$'])
6083 potential_paths= set(
6084 map(
6085lambda f: input_api.os_path.dirname(f.AbsoluteLocalPath()),
6086 input_api.AffectedFiles(include_deletes=False,
6087 file_filter=presubmit_py_filter)))
6088for full_pathin potential_paths:
Aleksey Khoroshilov2978c942022-06-13 16:14:12[diff] [blame]6089 test_file= input_api.os_path.join(full_path,'PRESUBMIT_test.py')
6090# The PRESUBMIT.py file (and the directory containing it) might have
6091# been affected by being moved or removed, so only try to run the tests
6092# if they still exist.
6093ifnot input_api.os_path.exists(test_file):
6094continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6095
Aleksey Khoroshilov2978c942022-06-13 16:14:12[diff] [blame]6096 results.extend(
6097 input_api.canned_checks.RunUnitTestsInDirectory(
6098 input_api,
6099 output_api,
6100 full_path,
Takuto Ikuta40def482023-06-02 02:23:49[diff] [blame]6101 files_to_check=[r'^PRESUBMIT_test\.py$']))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6102return results
maruel@chromium.org1f7b4172010-01-28 01:17:34[diff] [blame]6103
maruel@chromium.orgb337cb5b2011-01-23 21:24:05[diff] [blame]6104
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6105defCheckPatchFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6106 problems=[
6107 f.LocalPath()for fin input_api.AffectedFiles()
6108if f.LocalPath().endswith(('.orig','.rej'))
6109]
6110# Cargo.toml.orig files are part of third-party crates downloaded from
6111# crates.io and should be included.
6112 problems=[ffor fin problemsifnot f.endswith('Cargo.toml.orig')]
6113if problems:
6114return[
6115 output_api.PresubmitError("Don't commit .rej and .orig files.",
6116 problems)
6117]
6118else:
6119return[]
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]6120
6121
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6122defCheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6123# Excludes OS_CHROMEOS, which is not defined in build_config.h.
6124 macro_re= input_api.re.compile(
6125 r'^\s*#(el)?if.*\bdefined\(((COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
6126 include_re= input_api.re.compile(r'^#include\s+"build/build_config.h"',
6127 input_api.re.MULTILINE)
6128 extension_re= input_api.re.compile(r'\.[a-z]+$')
6129 errors=[]
Bruce Dawsonf7679202022-08-09 20:24:00[diff] [blame]6130 config_h_file= input_api.os_path.join('build','build_config.h')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6131for fin input_api.AffectedFiles(include_deletes=False):
Bruce Dawsonf7679202022-08-09 20:24:00[diff] [blame]6132# The build-config macros are allowed to be used in build_config.h
6133# without including itself.
6134if f.LocalPath()== config_h_file:
6135continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6136ifnot f.LocalPath().endswith(
6137('.h','.c','.cc','.cpp','.m','.mm')):
6138continue
Arthur Sonzognia3dec412024-04-29 12:05:37[diff] [blame]6139
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6140 found_line_number=None
6141 found_macro=None
6142 all_lines= input_api.ReadFile(f,'r').splitlines()
6143for line_num, linein enumerate(all_lines):
6144 match= macro_re.search(line)
6145if match:
6146 found_line_number= line_num
6147 found_macro= match.group(2)
6148break
6149ifnot found_line_number:
6150continue
Kent Tamura5a8755d2017-06-29 23:37:07[diff] [blame]6151
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6152 found_include_line=-1
6153for line_num, linein enumerate(all_lines):
6154if include_re.search(line):
6155 found_include_line= line_num
6156break
6157if found_include_line>=0and found_include_line< found_line_number:
6158continue
Kent Tamura5a8755d2017-06-29 23:37:07[diff] [blame]6159
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6160ifnot f.LocalPath().endswith('.h'):
6161 primary_header_path= extension_re.sub('.h', f.AbsoluteLocalPath())
6162try:
6163 content= input_api.ReadFile(primary_header_path,'r')
6164if include_re.search(content):
6165continue
6166exceptIOError:
6167pass
6168 errors.append('%s:%d %s macro is used without first including build/'
6169'build_config.h.'%
6170(f.LocalPath(), found_line_number, found_macro))
6171if errors:
6172return[output_api.PresubmitPromptWarning('\n'.join(errors))]
6173return[]
Kent Tamura5a8755d2017-06-29 23:37:07[diff] [blame]6174
6175
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]6176defCheckForSuperfluousStlIncludesInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6177 stl_include_re= input_api.re.compile(r'^#include\s+<('
6178 r'algorithm|'
6179 r'array|'
6180 r'limits|'
6181 r'list|'
6182 r'map|'
6183 r'memory|'
6184 r'queue|'
6185 r'set|'
6186 r'string|'
6187 r'unordered_map|'
6188 r'unordered_set|'
6189 r'utility|'
6190 r'vector)>')
6191 std_namespace_re= input_api.re.compile(r'std::')
6192 errors=[]
6193for fin input_api.AffectedFiles():
6194ifnot_IsCPlusPlusHeaderFile(input_api, f.LocalPath()):
6195continue
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]6196
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6197 uses_std_namespace=False
6198 has_stl_include=False
6199for linein f.NewContents():
6200if has_stl_includeand uses_std_namespace:
6201break
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]6202
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6203ifnot has_stl_includeand stl_include_re.search(line):
6204 has_stl_include=True
6205continue
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]6206
Bruce Dawson4a5579a2022-04-08 17:11:36[diff] [blame]6207ifnot uses_std_namespaceand(std_namespace_re.search(line)
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6208or'no-std-usage-because-pch-file'
6209in line):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6210 uses_std_namespace=True
6211continue
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]6212
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6213if has_stl_includeandnot uses_std_namespace:
6214 errors.append(
6215'%s: Includes STL header(s) but does not reference std::'%
6216 f.LocalPath())
6217if errors:
6218return[output_api.PresubmitPromptWarning('\n'.join(errors))]
6219return[]
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]6220
6221
Xiaohan Wang42d96c22022-01-20 17:23:11[diff] [blame]6222def_CheckForDeprecatedOSMacrosInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6223"""Check for sensible looking, totally invalid OS macros."""
6224 preprocessor_statement= input_api.re.compile(r'^\s*#')
6225 os_macro= input_api.re.compile(r'defined\(OS_([^)]+)\)')
6226 results=[]
6227for lnum, linein f.ChangedContents():
6228if preprocessor_statement.search(line):
6229for matchin os_macro.finditer(line):
6230 results.append(
6231' %s:%d: %s'%
6232(f.LocalPath(), lnum,'defined(OS_'+ match.group(1)+
6233') -> BUILDFLAG(IS_'+ match.group(1)+')'))
6234return results
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]6235
6236
Xiaohan Wang42d96c22022-01-20 17:23:11[diff] [blame]6237defCheckForDeprecatedOSMacros(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6238"""Check all affected files for invalid OS macros."""
6239 bad_macros=[]
Bruce Dawsonf7679202022-08-09 20:24:00[diff] [blame]6240# The OS_ macros are allowed to be used in build/build_config.h.
6241 config_h_file= input_api.os_path.join('build','build_config.h')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6242for fin input_api.AffectedSourceFiles(None):
Bruce Dawsonf7679202022-08-09 20:24:00[diff] [blame]6243ifnot f.LocalPath().endswith(('.py','.js','.html','.css','.md')) \
6244and f.LocalPath()!= config_h_file:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6245 bad_macros.extend(_CheckForDeprecatedOSMacrosInFile(input_api, f))
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]6246
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6247ifnot bad_macros:
6248return[]
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]6249
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6250return[
6251 output_api.PresubmitError(
6252'OS macros have been deprecated. Please use BUILDFLAGs instead (still '
6253'defined in build_config.h):', bad_macros)
6254]
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]6255
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]6256
6257def_CheckForInvalidIfDefinedMacrosInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6258"""Check all affected files for invalid "if defined" macros."""
6259 ALWAYS_DEFINED_MACROS=(
6260"TARGET_CPU_PPC",
6261"TARGET_CPU_PPC64",
6262"TARGET_CPU_68K",
6263"TARGET_CPU_X86",
6264"TARGET_CPU_ARM",
6265"TARGET_CPU_MIPS",
6266"TARGET_CPU_SPARC",
6267"TARGET_CPU_ALPHA",
6268"TARGET_IPHONE_SIMULATOR",
6269"TARGET_OS_EMBEDDED",
6270"TARGET_OS_IPHONE",
6271"TARGET_OS_MAC",
6272"TARGET_OS_UNIX",
6273"TARGET_OS_WIN32",
6274)
6275 ifdef_macro= input_api.re.compile(
6276 r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
6277 results=[]
6278for lnum, linein f.ChangedContents():
6279for matchin ifdef_macro.finditer(line):
6280if match.group(1)in ALWAYS_DEFINED_MACROS:
6281 always_defined=' %s is always defined. '% match.group(1)
6282 did_you_mean='Did you mean \'#if %s\'?'% match.group(1)
6283 results.append(
6284' %s:%d %s\n\t%s'%
6285(f.LocalPath(), lnum, always_defined, did_you_mean))
6286return results
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]6287
6288
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6289defCheckForInvalidIfDefinedMacros(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6290"""Check all affected files for invalid "if defined" macros."""
Arthur Sonzogni4fd14fd2024-06-02 18:42:52[diff] [blame]6291 SKIPPED_PATHS=[
6292'base/allocator/partition_allocator/src/partition_alloc/build_config.h',
6293'build/build_config.h',
6294'third_party/abseil-cpp/',
6295'third_party/sqlite/',
6296]
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6297
Arthur Sonzogni4fd14fd2024-06-02 18:42:52[diff] [blame]6298def affected_files_filter(f):
6299# Normalize the local path to Linux-style path separators so that the
6300# path comparisons work on Windows as well.
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]6301 path= f.UnixLocalPath()
Arthur Sonzogni4fd14fd2024-06-02 18:42:52[diff] [blame]6302
6303for skipped_pathin SKIPPED_PATHS:
6304if path.startswith(skipped_path):
6305returnFalse
6306
6307return path.endswith(('.h','.c','.cc','.m','.mm'))
6308
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6309 bad_macros=[]
Arthur Sonzogni4fd14fd2024-06-02 18:42:52[diff] [blame]6310for fin input_api.AffectedSourceFiles(affected_files_filter):
6311 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]6312
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6313ifnot bad_macros:
6314return[]
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]6315
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6316return[
6317 output_api.PresubmitError(
6318'Found ifdef check on always-defined macro[s]. Please fix your code\n'
6319'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
6320 bad_macros)
6321]
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]6322
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6323
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6324defCheckForIPCRules(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6325"""Check for same IPC rules described in
6326 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
6327 """
6328 base_pattern= r'IPC_ENUM_TRAITS\('
6329 inclusion_pattern= input_api.re.compile(r'(%s)'% base_pattern)
6330 comment_pattern= input_api.re.compile(r'//.*(%s)'% base_pattern)
mlamouria82272622014-09-16 18:45:04[diff] [blame]6331
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6332 problems=[]
6333for fin input_api.AffectedSourceFiles(None):
6334 local_path= f.LocalPath()
6335ifnot local_path.endswith('.h'):
6336continue
6337for line_number, linein f.ChangedContents():
6338if inclusion_pattern.search(
6339 line)andnot comment_pattern.search(line):
6340 problems.append('%s:%d\n %s'%
6341(local_path, line_number, line.strip()))
mlamouria82272622014-09-16 18:45:04[diff] [blame]6342
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6343if problems:
6344return[
6345 output_api.PresubmitPromptWarning(_IPC_ENUM_TRAITS_DEPRECATED,
6346 problems)
6347]
6348else:
6349return[]
mlamouria82272622014-09-16 18:45:04[diff] [blame]6350
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]6351
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6352defCheckForLongPathnames(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6353"""Check to make sure no files being submitted have long paths.
6354 This causes issues on Windows.
6355 """
6356 problems=[]
6357for fin input_api.AffectedTestableFiles():
6358 local_path= f.LocalPath()
6359# Windows has a path limit of 260 characters. Limit path length to 200 so
6360# that we have some extra for the prefix on dev machines and the bots.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6361if(local_path.startswith('third_party/blink/web_tests/platform/')
6362andnot local_path.startswith(
6363'third_party/blink/web_tests/platform/win')):
Weizhong Xia8b461f12024-06-21 21:46:33[diff] [blame]6364# Do not check length of the path for files not used by Windows
6365continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6366if len(local_path)>200:
6367 problems.append(local_path)
Stephen Martinis97a394142018-06-07 23:06:05[diff] [blame]6368
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6369if problems:
6370return[output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
6371else:
6372return[]
Stephen Martinis97a394142018-06-07 23:06:05[diff] [blame]6373
6374
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6375defCheckForIncludeGuards(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6376"""Check that header files have proper guards against multiple inclusion.
6377 If a file should not have such guards (and it probably should) then it
Bruce Dawson4a5579a2022-04-08 17:11:36[diff] [blame]6378 should include the string "no-include-guard-because-multiply-included" or
6379 "no-include-guard-because-pch-file".
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6380 """
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6381
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6382def is_chromium_header_file(f):
6383# We only check header files under the control of the Chromium
mikt84d6c712024-03-27 13:29:03[diff] [blame]6384# project. This excludes:
6385# - third_party/*, except blink.
6386# - base/allocator/partition_allocator/: PartitionAlloc is a standalone
6387# library used outside of Chrome. Includes are referenced from its
6388# own base directory. It has its own `CheckForIncludeGuards`
6389# PRESUBMIT.py check.
6390# - *_message_generator.h: They use include guards in a special,
6391# non-typical way.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6392 file_with_path= input_api.os_path.normpath(f.LocalPath())
6393return(file_with_path.endswith('.h')
6394andnot file_with_path.endswith('_message_generator.h')
Bruce Dawson4c4c2922022-05-02 18:07:33[diff] [blame]6395andnot file_with_path.endswith('com_imported_mstscax.h')
Peter Kasting66c1f752024-12-02 15:28:37[diff] [blame]6396andnot file_with_path.startswith(
6397 input_api.os_path.join('base','allocator',
6398'partition_allocator'))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6399and(not file_with_path.startswith('third_party')
6400or file_with_path.startswith(
6401 input_api.os_path.join('third_party','blink'))))
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6402
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6403def replace_special_with_underscore(string):
6404return input_api.re.sub(r'[+\\/.-]','_', string)
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6405
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6406 errors=[]
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6407
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6408for fin input_api.AffectedSourceFiles(is_chromium_header_file):
6409 guard_name=None
6410 guard_line_number=None
6411 seen_guard_end=False
Lei Zhangd84f9512024-05-28 19:43:30[diff] [blame]6412 bypass_checks_at_end_of_file=False
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6413
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6414 file_with_path= input_api.os_path.normpath(f.LocalPath())
6415 base_file_name= input_api.os_path.splitext(
6416 input_api.os_path.basename(file_with_path))[0]
6417 upper_base_file_name= base_file_name.upper()
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6418
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6419 expected_guard= replace_special_with_underscore(
6420 file_with_path.upper()+'_')
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6421
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6422# For "path/elem/file_name.h" we should really only accept
6423# PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
6424# are too many (1000+) files with slight deviations from the
6425# coding style. The most important part is that the include guard
6426# is there, and that it's unique, not the name so this check is
6427# forgiving for existing files.
6428#
6429# As code becomes more uniform, this could be made stricter.
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6430
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6431 guard_name_pattern_list=[
6432# Anything with the right suffix (maybe with an extra _).
6433 r'\w+_H__?',
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6434
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6435# To cover include guards with old Blink style.
6436 r'\w+_h',
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6437
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6438# Anything including the uppercase name of the file.
6439 r'\w*'+ input_api.re.escape(
6440 replace_special_with_underscore(upper_base_file_name))+
6441 r'\w*',
6442]
6443 guard_name_pattern='|'.join(guard_name_pattern_list)
6444 guard_pattern= input_api.re.compile(r'#ifndef\s+('+
6445 guard_name_pattern+')')
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6446
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6447for line_number, linein enumerate(f.NewContents()):
Bruce Dawson4a5579a2022-04-08 17:11:36[diff] [blame]6448if('no-include-guard-because-multiply-included'in line
6449or'no-include-guard-because-pch-file'in line):
Lei Zhangd84f9512024-05-28 19:43:30[diff] [blame]6450 bypass_checks_at_end_of_file=True
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6451break
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6452
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6453if guard_nameisNone:
6454 match= guard_pattern.match(line)
6455if match:
6456 guard_name= match.group(1)
6457 guard_line_number= line_number
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6458
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6459# We allow existing files to use include guards whose names
6460# don't match the chromium style guide, but new files should
6461# get it right.
Bruce Dawson6cc154e2022-04-12 20:39:49[diff] [blame]6462if guard_name!= expected_guard:
Bruce Dawson95eb7562022-09-14 15:27:16[diff] [blame]6463if f.Action()=='A':# If file was just 'A'dded
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6464 errors.append(
6465 output_api.PresubmitPromptWarning(
6466'Header using the wrong include guard name %s'
6467% guard_name,[
6468'%s:%d'%
6469(f.LocalPath(), line_number+1)
6470],'Expected: %r\nFound: %r'%
6471(expected_guard, guard_name)))
6472else:
6473# The line after #ifndef should have a #define of the same name.
6474if line_number== guard_line_number+1:
6475 expected_line='#define %s'% guard_name
6476if line!= expected_line:
6477 errors.append(
6478 output_api.PresubmitPromptWarning(
6479'Missing "%s" for include guard'%
6480 expected_line,
6481['%s:%d'%(f.LocalPath(), line_number+1)],
6482'Expected: %r\nGot: %r'%
6483(expected_line, line)))
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6484
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6485ifnot seen_guard_endand line=='#endif // %s'% guard_name:
6486 seen_guard_end=True
6487elif seen_guard_end:
6488if line.strip()!='':
6489 errors.append(
6490 output_api.PresubmitPromptWarning(
6491'Include guard %s not covering the whole file'
6492%(guard_name),[f.LocalPath()]))
6493break# Nothing else to check and enough to warn once.
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6494
Lei Zhangd84f9512024-05-28 19:43:30[diff] [blame]6495if bypass_checks_at_end_of_file:
6496continue
6497
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6498if guard_nameisNone:
6499 errors.append(
6500 output_api.PresubmitPromptWarning(
Bruce Dawson32114b62022-04-11 16:45:49[diff] [blame]6501'Missing include guard in %s\n'
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6502'Recommended name: %s\n'
6503'This check can be disabled by having the string\n'
Bruce Dawson4a5579a2022-04-08 17:11:36[diff] [blame]6504'"no-include-guard-because-multiply-included" or\n'
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6505'"no-include-guard-because-pch-file" in the header.'%
6506(f.LocalPath(), expected_guard)))
Lei Zhangd84f9512024-05-28 19:43:30[diff] [blame]6507elifnot seen_guard_end:
6508 errors.append(
6509 output_api.PresubmitPromptWarning(
6510'Incorrect or missing include guard #endif in %s\n'
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6511'Recommended #endif comment: // %s'%
6512(f.LocalPath(), expected_guard)))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6513
6514return errors
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]6515
6516
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6517defCheckForWindowsLineEndings(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6518"""Check source code and known ascii text files for Windows style line
6519 endings.
6520 """
Bruce Dawson5efbdc652022-04-11 19:29:51[diff] [blame]6521 known_text_files= r'.*\.(txt|html|htm|py|gyp|gypi|gn|isolate|icon)$'
mostynbb639aca52015-01-07 20:31:23[diff] [blame]6522
dpapadfd421fb2025-02-13 00:47:32[diff] [blame]6523 _WEBUI_FILES_EXTENSIONS= r'\.(css|html|js|ts|svg)$'
6524
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6525 file_inclusion_pattern=(known_text_files,
6526 r'.+%s'% _IMPLEMENTATION_EXTENSIONS,
dpapadfd421fb2025-02-13 00:47:32[diff] [blame]6527 r'.+%s'% _HEADER_EXTENSIONS,
6528 r'.+%s'% _WEBUI_FILES_EXTENSIONS)
6529
6530# Exclude folder that contains .ts files that are actually binary video
6531# format and not TypeScript.
6532 file_exclusion_pattern=(r'media/test/data/')
mostynbb639aca52015-01-07 20:31:23[diff] [blame]6533
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6534 problems=[]
6535 source_file_filter=lambda f: input_api.FilterSourceFile(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6536 f,
6537 files_to_check=file_inclusion_pattern,
dpapadfd421fb2025-02-13 00:47:32[diff] [blame]6538 files_to_skip=file_exclusion_pattern)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6539for fin input_api.AffectedSourceFiles(source_file_filter):
Bruce Dawson5efbdc652022-04-11 19:29:51[diff] [blame]6540# Ignore test files that contain crlf intentionally.
6541if f.LocalPath().endswith('crlf.txt'):
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]6542continue
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6543 include_file=False
6544for linein input_api.ReadFile(f,'r').splitlines(True):
6545if line.endswith('\r\n'):
6546 include_file=True
6547if include_file:
6548 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:23[diff] [blame]6549
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6550if problems:
6551return[
6552 output_api.PresubmitPromptWarning(
6553'Are you sure that you want '
6554'these files to contain Windows style line endings?\n'+
6555'\n'.join(problems))
6556]
mostynbb639aca52015-01-07 20:31:23[diff] [blame]6557
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6558return[]
6559
mostynbb639aca52015-01-07 20:31:23[diff] [blame]6560
Evan Stade6cfc964c12021-05-18 20:21:16[diff] [blame]6561defCheckIconFilesForLicenseHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6562"""Check that .icon files (which are fragments of C++) have license headers.
6563 """
Evan Stade6cfc964c12021-05-18 20:21:16[diff] [blame]6564
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6565 icon_files=(r'.*\.icon$',)
Evan Stade6cfc964c12021-05-18 20:21:16[diff] [blame]6566
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6567 icons=lambda x: input_api.FilterSourceFile(x, files_to_check=icon_files)
6568return input_api.canned_checks.CheckLicense(input_api,
6569 output_api,
6570 source_file_filter=icons)
6571
Evan Stade6cfc964c12021-05-18 20:21:16[diff] [blame]6572
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6573defCheckForUseOfChromeAppsDeprecations(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6574"""Check source code for use of Chrome App technologies being
6575 deprecated.
6576 """
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6577
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6578def_CheckForDeprecatedTech(input_api,
6579 output_api,
6580 detection_list,
6581 files_to_check=None,
6582 files_to_skip=None):
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6583
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6584if(files_to_checkor files_to_skip):
6585 source_file_filter=lambda f: input_api.FilterSourceFile(
6586 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
6587else:
6588 source_file_filter=None
6589
6590 problems=[]
6591
6592for fin input_api.AffectedSourceFiles(source_file_filter):
6593if f.Action()=='D':
6594continue
6595for _, linein f.ChangedContents():
6596if any(detectin linefor detectin detection_list):
6597 problems.append(f.LocalPath())
6598
6599return problems
6600
6601# to avoid this presubmit script triggering warnings
6602 files_to_skip=['PRESUBMIT.py','PRESUBMIT_test.py']
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6603
6604 problems=[]
6605
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6606# NMF: any files with extensions .nmf or NMF
6607 _NMF_FILES= r'\.(nmf|NMF)$'
6608 problems+=_CheckForDeprecatedTech(
6609 input_api,
6610 output_api,
6611 detection_list=[''],# any change to the file will trigger warning
6612 files_to_check=[r'.+%s'% _NMF_FILES])
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6613
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6614# MANIFEST: any manifest.json that in its diff includes "app":
6615 _MANIFEST_FILES= r'(manifest\.json)$'
6616 problems+=_CheckForDeprecatedTech(
6617 input_api,
6618 output_api,
6619 detection_list=['"app":'],
6620 files_to_check=[r'.*%s'% _MANIFEST_FILES])
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6621
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6622# NaCl / PNaCl: any file that in its diff contains the strings in the list
6623 problems+=_CheckForDeprecatedTech(
6624 input_api,
6625 output_api,
6626 detection_list=['config=nacl','enable-nacl','cpu=pnacl','nacl_io'],
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]6627 files_to_skip=files_to_skip+[r"^native_client_sdk/"])
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6628
Gao Shenga79ebd42022-08-08 17:25:59[diff] [blame]6629# PPAPI: any C/C++ file that in its diff includes a ppapi library
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6630 problems+=_CheckForDeprecatedTech(
6631 input_api,
6632 output_api,
6633 detection_list=['#include "ppapi','#include <ppapi'],
6634 files_to_check=(r'.+%s'% _HEADER_EXTENSIONS,
6635 r'.+%s'% _IMPLEMENTATION_EXTENSIONS),
Bruce Dawson40fece62022-09-16 19:58:31[diff] [blame]6636 files_to_skip=[r"^ppapi/"])
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6637
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6638if problems:
6639return[
6640 output_api.PresubmitPromptWarning(
6641'You are adding/modifying code'
6642'related to technologies which will soon be deprecated (Chrome Apps, NaCl,'
6643' PNaCl, PPAPI). See this blog post for more details:\n'
6644'https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html\n'
6645'and this documentation for options to replace these technologies:\n'
6646'https://developer.chrome.com/docs/apps/migration/\n'+
6647'\n'.join(problems))
6648]
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6649
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6650return[]
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]6651
mostynbb639aca52015-01-07 20:31:23[diff] [blame]6652
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6653defCheckSyslogUseWarningOnUpload(input_api, output_api, src_file_filter=None):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6654"""Checks that all source files use SYSLOG properly."""
6655 syslog_files=[]
6656for fin input_api.AffectedSourceFiles(src_file_filter):
6657for line_number, linein f.ChangedContents():
6658if'SYSLOG'in line:
6659 syslog_files.append(f.LocalPath()+':'+ str(line_number))
pastarmovj032ba5bc2017-01-12 10:41:56[diff] [blame]6660
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6661if syslog_files:
6662return[
6663 output_api.PresubmitPromptWarning(
6664'Please make sure there are no privacy sensitive bits of data in SYSLOG'
6665' calls.\nFiles to check:\n',
6666 items=syslog_files)
6667]
6668return[]
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]6669
6670
maruel@chromium.org1f7b4172010-01-28 01:17:34[diff] [blame]6671defCheckChangeOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6672if input_api.version<[2,0,0]:
6673return[
6674 output_api.PresubmitError(
6675"Your depot_tools is out of date. "
6676"This PRESUBMIT.py requires at least presubmit_support version 2.0.0, "
6677"but your version is %d.%d.%d"% tuple(input_api.version))
6678]
6679 results=[]
6680 results.extend(
6681 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
6682return results
maruel@chromium.orgca8d19842009-02-19 16:33:12[diff] [blame]6683
6684
6685defCheckChangeOnCommit(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6686if input_api.version<[2,0,0]:
6687return[
6688 output_api.PresubmitError(
6689"Your depot_tools is out of date. "
6690"This PRESUBMIT.py requires at least presubmit_support version 2.0.0, "
6691"but your version is %d.%d.%d"% tuple(input_api.version))
6692]
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6693
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6694 results=[]
6695# Make sure the tree is 'open'.
6696 results.extend(
6697 input_api.canned_checks.CheckTreeIsOpen(
6698 input_api,
6699 output_api,
6700 json_url='http://chromium-status.appspot.com/current?format=json'))
maruel@chromium.org806e98e2010-03-19 17:49:27[diff] [blame]6701
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6702 results.extend(
6703 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
6704 results.extend(
6705 input_api.canned_checks.CheckChangeHasBugField(input_api, output_api))
6706 results.extend(
6707 input_api.canned_checks.CheckChangeHasNoUnwantedTags(
6708 input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6709return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6710
6711
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]6712defCheckStrings(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6713"""Check string ICU syntax validity and if translation screenshots exist."""
6714# Skip translation screenshots check if a SkipTranslationScreenshotsCheck
6715# footer is set to true.
6716 git_footers= input_api.change.GitFootersFromDescription()
6717 skip_screenshot_check_footer=[
6718 footer.lower()for footerin git_footers.get(
6719 u'Skip-Translation-Screenshots-Check',[])
6720]
6721 run_screenshot_check= u'true'notin skip_screenshot_check_footer
Edward Lesmesf7c5c6d2020-05-14 23:30:02[diff] [blame]6722
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6723import os
6724import re
6725import sys
6726from ioimportStringIO
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6727
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6728 new_or_added_paths= set(f.LocalPath()for fin input_api.AffectedFiles()
6729if(f.Action()=='A'or f.Action()=='M'))
6730 removed_paths= set(f.LocalPath()
6731for fin input_api.AffectedFiles(include_deletes=True)
6732if f.Action()=='D')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6733
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6734 affected_grds=[
6735 ffor fin input_api.AffectedFiles()
6736if f.LocalPath().endswith(('.grd','.grdp'))
6737]
6738 affected_grds=[
6739 ffor fin affected_grdsifnot'testdata'in f.LocalPath()
6740]
6741ifnot affected_grds:
6742return[]
meacer8c0d3832019-12-26 21:46:16[diff] [blame]6743
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6744 affected_png_paths=[
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]6745 f.LocalPath()for fin input_api.AffectedFiles()
6746if f.LocalPath().endswith('.png')
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6747]
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6748
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6749# Check for screenshots. Developers can upload screenshots using
6750# tools/translation/upload_screenshots.py which finds and uploads
6751# images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
6752# message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
6753# test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
6754#
6755# The logic here is as follows:
6756#
6757# - If the CL has a .png file under the screenshots directory for a grd
6758# file, warn the developer. Actual images should never be checked into the
6759# Chrome repo.
6760#
6761# - If the CL contains modified or new messages in grd files and doesn't
6762# contain the corresponding .sha1 files, warn the developer to add images
6763# and upload them via tools/translation/upload_screenshots.py.
6764#
6765# - If the CL contains modified or new messages in grd files and the
6766# corresponding .sha1 files, everything looks good.
6767#
6768# - If the CL contains removed messages in grd files but the corresponding
6769# .sha1 files aren't removed, warn the developer to remove them.
6770 unnecessary_screenshots=[]
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]6771 invalid_sha1=[]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6772 missing_sha1=[]
Bruce Dawson55776c42022-12-09 17:23:47[diff] [blame]6773 missing_sha1_modified=[]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6774 unnecessary_sha1_files=[]
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6775
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6776# This checks verifies that the ICU syntax of messages this CL touched is
6777# valid, and reports any found syntax errors.
6778# Without this presubmit check, ICU syntax errors in Chromium strings can land
6779# without developers being aware of them. Later on, such ICU syntax errors
6780# break message extraction for translation, hence would block Chromium
6781# translations until they are fixed.
6782 icu_syntax_errors=[]
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]6783 sha1_pattern= input_api.re.compile(r'^[a-fA-F0-9]{40}$',
6784 input_api.re.MULTILINE)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6785
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6786def_CheckScreenshotAdded(screenshots_dir, message_id):
6787 sha1_path= input_api.os_path.join(screenshots_dir,
6788 message_id+'.png.sha1')
6789if sha1_pathnotin new_or_added_paths:
6790 missing_sha1.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]6791elifnot_CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:25[diff] [blame]6792 invalid_sha1.append(sha1_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6793
Bruce Dawson55776c42022-12-09 17:23:47[diff] [blame]6794def_CheckScreenshotModified(screenshots_dir, message_id):
6795 sha1_path= input_api.os_path.join(screenshots_dir,
6796 message_id+'.png.sha1')
6797if sha1_pathnotin new_or_added_paths:
6798 missing_sha1_modified.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]6799elifnot_CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:25[diff] [blame]6800 invalid_sha1.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]6801
6802def_CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:25[diff] [blame]6803return sha1_pattern.search(
6804 next("\n".join(f.NewContents())for fin input_api.AffectedFiles()
6805if f.LocalPath()== sha1_path))
Bruce Dawson55776c42022-12-09 17:23:47[diff] [blame]6806
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6807def_CheckScreenshotRemoved(screenshots_dir, message_id):
6808 sha1_path= input_api.os_path.join(screenshots_dir,
6809 message_id+'.png.sha1')
6810if input_api.os_path.exists(
6811 sha1_path)and sha1_pathnotin removed_paths:
6812 unnecessary_sha1_files.append(sha1_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6813
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6814def_ValidateIcuSyntax(text, level, signatures):
6815"""Validates ICU syntax of a text string.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]6816
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6817 Check if text looks similar to ICU and checks for ICU syntax correctness
6818 in this case. Reports various issues with ICU syntax and values of
6819 variants. Supports checking of nested messages. Accumulate information of
6820 each ICU messages found in the text for further checking.
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6821
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6822 Args:
6823 text: a string to check.
6824 level: a number of current nesting level.
6825 signatures: an accumulator, a list of tuple of (level, variable,
6826 kind, variants).
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6827
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6828 Returns:
6829 None if a string is not ICU or no issue detected.
6830 A tuple of (message, start index, end index) if an issue detected.
6831 """
6832 valid_types={
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6833'plural':(frozenset([
6834'=0','=1','=2','=3','zero','one','two','few','many',
6835'other'
6836]), frozenset(['=1','other'])),
6837'selectordinal':(frozenset([
6838'=0','=1','=2','=3','zero','one','two','few','many',
6839'other'
6840]), frozenset(['one','other'])),
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6841'select':(frozenset(), frozenset(['other'])),
6842}
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6843
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6844# Check if the message looks like an attempt to use ICU
6845# plural. If yes - check if its syntax strictly matches ICU format.
6846 like= re.match(r'^[^{]*\{[^{]*\b(plural|selectordinal|select)\b',
6847 text)
6848ifnot like:
6849 signatures.append((level,None,None,None))
6850return
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6851
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6852# Check for valid prefix and suffix
6853 m= re.match(
6854 r'^([^{]*\{)([a-zA-Z0-9_]+),\s*'
6855 r'(plural|selectordinal|select),\s*'
6856 r'(?:offset:\d+)?\s*(.*)', text, re.DOTALL)
6857ifnot m:
6858return(('This message looks like an ICU plural, '
6859'but does not follow ICU syntax.'), like.start(),
6860 like.end())
6861 starting, variable, kind, variant_pairs= m.groups()
6862 variants, depth, last_pos=_ParseIcuVariants(variant_pairs,
6863 m.start(4))
6864if depth:
6865return('Invalid ICU format. Unbalanced opening bracket', last_pos,
6866 len(text))
6867 first= text[0]
6868 ending= text[last_pos:]
6869ifnot starting:
6870return('Invalid ICU format. No initial opening bracket',
6871 last_pos-1, last_pos)
6872ifnot endingor'}'notin ending:
6873return('Invalid ICU format. No final closing bracket',
6874 last_pos-1, last_pos)
6875elif first!='{':
6876return((
6877'Invalid ICU format. Extra characters at the start of a complex '
6878'message (go/icu-message-migration): "%s"')% starting,0,
6879 len(starting))
6880elif ending!='}':
6881return((
6882'Invalid ICU format. Extra characters at the end of a complex '
6883'message (go/icu-message-migration): "%s"')% ending,
6884 last_pos-1, len(text)-1)
6885if kindnotin valid_types:
6886return(('Unknown ICU message type %s. '
6887'Valid types are: plural, select, selectordinal')% kind,
68880,0)
6889 known, required= valid_types[kind]
6890 defined_variants= set()
6891for variant, variant_range, value, value_rangein variants:
6892 start, end= variant_range
6893if variantin defined_variants:
6894return('Variant "%s" is defined more than once'% variant,
6895 start, end)
6896elif knownand variantnotin known:
6897return('Variant "%s" is not valid for %s message'%
6898(variant, kind), start, end)
6899 defined_variants.add(variant)
6900# Check for nested structure
6901 res=_ValidateIcuSyntax(value[1:-1], level+1, signatures)
6902if res:
6903return(res[0], res[1]+ value_range[0]+1,
6904 res[2]+ value_range[0]+1)
6905 missing= required- defined_variants
6906if missing:
6907return('Required variants missing: %s'%', '.join(missing),0,
6908 len(text))
6909 signatures.append((level, variable, kind, defined_variants))
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6910
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6911def_ParseIcuVariants(text, offset=0):
6912"""Parse variants part of ICU complex message.
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6913
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6914 Builds a tuple of variant names and values, as well as
6915 their offsets in the input string.
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6916
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6917 Args:
6918 text: a string to parse
6919 offset: additional offset to add to positions in the text to get correct
6920 position in the complete ICU string.
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6921
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6922 Returns:
6923 List of tuples, each tuple consist of four fields: variant name,
6924 variant name span (tuple of two integers), variant value, value
6925 span (tuple of two integers).
6926 """
6927 depth, start, end=0,-1,-1
6928 variants=[]
6929 key=None
6930for idx, charin enumerate(text):
6931if char=='{':
6932ifnot depth:
6933 start= idx
6934 chunk= text[end+1:start]
6935 key= chunk.strip()
6936 pos= offset+ end+1+ chunk.find(key)
6937 span=(pos, pos+ len(key))
6938 depth+=1
6939elif char=='}':
6940ifnot depth:
6941return variants, depth, offset+ idx
6942 depth-=1
6943ifnot depth:
6944 end= idx
6945 variants.append((key, span, text[start:end+1],
6946(offset+ start, offset+ end+1)))
6947return variants, depth, offset+ end+1
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6948
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]6949 old_sys_path= sys.path
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6950try:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6951 sys.path= sys.path+[
6952 input_api.os_path.join(input_api.PresubmitLocalPath(),'tools',
6953'translation')
6954]
6955from helperimport grd_helper
6956finally:
6957 sys.path= old_sys_path
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6958
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6959for fin affected_grds:
6960 file_path= f.LocalPath()
6961 old_id_to_msg_map={}
6962 new_id_to_msg_map={}
6963# Note that this code doesn't check if the file has been deleted. This is
6964# OK because it only uses the old and new file contents and doesn't load
6965# the file via its path.
6966# It's also possible that a file's content refers to a renamed or deleted
6967# file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
6968# is OK as well, because grd_helper ignores <part> tags when loading .grd or
6969# .grdp files.
6970if file_path.endswith('.grdp'):
6971if f.OldContents():
6972 old_id_to_msg_map= grd_helper.GetGrdpMessagesFromString(
6973'\n'.join(f.OldContents()))
6974if f.NewContents():
6975 new_id_to_msg_map= grd_helper.GetGrdpMessagesFromString(
6976'\n'.join(f.NewContents()))
6977else:
6978 file_dir= input_api.os_path.dirname(file_path)or'.'
6979if f.OldContents():
6980 old_id_to_msg_map= grd_helper.GetGrdMessages(
6981StringIO('\n'.join(f.OldContents())), file_dir)
6982if f.NewContents():
6983 new_id_to_msg_map= grd_helper.GetGrdMessages(
6984StringIO('\n'.join(f.NewContents())), file_dir)
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6985
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6986 grd_name, ext= input_api.os_path.splitext(
6987 input_api.os_path.basename(file_path))
6988 screenshots_dir= input_api.os_path.join(
6989 input_api.os_path.dirname(file_path),
6990 grd_name+ ext.replace('.','_'))
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]6991
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]6992# Compute added, removed and modified message IDs.
6993 old_ids= set(old_id_to_msg_map)
6994 new_ids= set(new_id_to_msg_map)
6995 added_ids= new_ids- old_ids
6996 removed_ids= old_ids- new_ids
6997 modified_ids= set([])
6998for keyin old_ids.intersection(new_ids):
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]6999if(old_id_to_msg_map[key].ContentsAsXml('',True)
7000!= new_id_to_msg_map[key].ContentsAsXml('',True)):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7001# The message content itself changed. Require an updated screenshot.
7002 modified_ids.add(key)
7003elif old_id_to_msg_map[key].attrs['meaning']!= \
7004 new_id_to_msg_map[key].attrs['meaning']:
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]7005# The message meaning changed. We later check for a screenshot.
7006 modified_ids.add(key)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]7007
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7008if run_screenshot_check:
7009# Check the screenshot directory for .png files. Warn if there is any.
7010for png_pathin affected_png_paths:
7011if png_path.startswith(screenshots_dir):
7012 unnecessary_screenshots.append(png_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]7013
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7014for added_idin added_ids:
7015_CheckScreenshotAdded(screenshots_dir, added_id)
Rainhard Findlingd8d04372020-08-13 13:30:09[diff] [blame]7016
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7017for modified_idin modified_ids:
Bruce Dawson55776c42022-12-09 17:23:47[diff] [blame]7018_CheckScreenshotModified(screenshots_dir, modified_id)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]7019
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7020for removed_idin removed_ids:
7021_CheckScreenshotRemoved(screenshots_dir, removed_id)
7022
7023# Check new and changed strings for ICU syntax errors.
7024for keyin added_ids.union(modified_ids):
7025 msg= new_id_to_msg_map[key].ContentsAsXml('',True)
7026 err=_ValidateIcuSyntax(msg,0,[])
7027if errisnotNone:
7028 icu_syntax_errors.append(str(key)+': '+ str(err[0]))
7029
7030 results=[]
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]7031if run_screenshot_check:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7032if unnecessary_screenshots:
7033 results.append(
7034 output_api.PresubmitError(
7035'Do not include actual screenshots in the changelist. Run '
7036'tools/translate/upload_screenshots.py to upload them instead:',
7037 sorted(unnecessary_screenshots)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]7038
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7039if missing_sha1:
7040 results.append(
7041 output_api.PresubmitError(
Bruce Dawson55776c42022-12-09 17:23:47[diff] [blame]7042'You are adding UI strings.\n'
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7043'To ensure the best translations, take screenshots of the relevant UI '
7044'(https://g.co/chrome/translation) and add these files to your '
7045'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]7046
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]7047if invalid_sha1:
7048 results.append(
7049 output_api.PresubmitError(
7050'The following files do not seem to contain valid sha1 hashes. '
7051'Make sure they contain hashes created by '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7052'tools/translate/upload_screenshots.py:',
7053 sorted(invalid_sha1)))
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]7054
Bruce Dawson55776c42022-12-09 17:23:47[diff] [blame]7055if missing_sha1_modified:
7056 results.append(
7057 output_api.PresubmitError(
7058'You are modifying UI strings or their meanings.\n'
7059'To ensure the best translations, take screenshots of the relevant UI '
7060'(https://g.co/chrome/translation) and add these files to your '
7061'changelist:', sorted(missing_sha1_modified)))
7062
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7063if unnecessary_sha1_files:
7064 results.append(
7065 output_api.PresubmitError(
7066'You removed strings associated with these files. Remove:',
7067 sorted(unnecessary_sha1_files)))
7068else:
7069 results.append(
7070 output_api.PresubmitPromptOrNotify('Skipping translation '
7071'screenshots check.'))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]7072
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7073if icu_syntax_errors:
7074 results.append(
7075 output_api.PresubmitPromptWarning(
7076'ICU syntax errors were found in the following strings (problems or '
7077'feedback? Contact rainhard@chromium.org):',
7078 items=icu_syntax_errors))
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]7079
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7080return results
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]7081
7082
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7083defCheckTranslationExpectations(input_api,
7084 output_api,
7085 repo_root=None,
7086 translation_expectations_path=None,
7087 grd_files=None):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7088import sys
7089 affected_grds=[
7090 ffor fin input_api.AffectedFiles()
7091if(f.LocalPath().endswith('.grd')or f.LocalPath().endswith('.grdp'))
7092]
7093ifnot affected_grds:
7094return[]
7095
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]7096 old_sys_path= sys.path
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7097try:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7098 sys.path= sys.path+[
7099 input_api.os_path.join(input_api.PresubmitLocalPath(),'tools',
7100'translation')
7101]
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]7102 sys.path= sys.path+[
7103 input_api.os_path.join(input_api.PresubmitLocalPath(),
7104'third_party','depot_tools')
7105]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7106from helperimport git_helper
7107from helperimport translation_helper
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]7108import gclient_utils
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7109finally:
7110 sys.path= old_sys_path
7111
7112# Check that translation expectations can be parsed and we can get a list of
7113# translatable grd files. |repo_root| and |translation_expectations_path| are
7114# only passed by tests.
7115ifnot repo_root:
7116 repo_root= input_api.PresubmitLocalPath()
7117ifnot translation_expectations_path:
7118 translation_expectations_path= input_api.os_path.join(
7119 repo_root,'tools','gritsettings','translation_expectations.pyl')
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]7120 is_cog= gclient_utils.IsEnvCog()
7121# Git is not available in cog workspaces.
7122ifnot grd_filesandnot is_cog:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7123 grd_files= git_helper.list_grds_in_repository(repo_root)
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]7124ifnot grd_files:
7125 grd_files=[]
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7126
7127# Ignore bogus grd files used only for testing
Gao Shenga79ebd42022-08-08 17:25:59[diff] [blame]7128# ui/webui/resources/tools/generate_grd.py.
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7129 ignore_path= input_api.os_path.join('ui','webui','resources','tools',
7130'tests')
7131 grd_files=[pfor pin grd_filesif ignore_pathnotin p]
7132
Ben Mason5d4c3242025-04-15 20:28:37[diff] [blame]7133# Ensure no duplicate basenames.
7134 basename_to_src_paths={}
7135for grd_pathin grd_files:
7136 basename= input_api.os_path.basename(grd_path)
7137 basename_to_src_paths.setdefault(basename,[])
7138 basename_to_src_paths[basename].append(grd_path)
7139for src_pathsin basename_to_src_paths.values():
7140if len(src_paths)>1:
7141return[
7142 output_api.PresubmitNotifyResult(
7143'Multiple string files have the same basename. This will result in '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7144'missing translations. Files: %s'%', '.join(src_paths))
Ben Mason5d4c3242025-04-15 20:28:37[diff] [blame]7145]
7146
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7147try:
7148 translation_helper.get_translatable_grds(
Terrence Reilly313f44ff2025-01-22 15:10:14[diff] [blame]7149 repo_root, grd_files, translation_expectations_path, is_cog)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7150exceptExceptionas e:
7151return[
7152 output_api.PresubmitNotifyResult(
7153'Failed to get a list of translatable grd files. This happens when:\n'
7154' - One of the modified grd or grdp files cannot be parsed or\n'
7155' - %s is not updated.\n'
7156'Stack:\n%s'%(translation_expectations_path, str(e)))
7157]
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]7158return[]
7159
Ken Rockotc31f4832020-05-29 18:58:51[diff] [blame]7160
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]7161defCheckStableMojomChanges(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7162"""Changes to [Stable] mojom types must preserve backward-compatibility."""
7163 changed_mojoms= input_api.AffectedFiles(
7164 include_deletes=True,
7165 file_filter=lambda f: f.LocalPath().endswith(('.mojom')))
Erik Staabc734cd7a2021-11-23 03:11:52[diff] [blame]7166
Bruce Dawson344ab262022-06-04 11:35:10[diff] [blame]7167ifnot changed_mojomsor input_api.no_diffs:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7168return[]
7169
7170 delta=[]
7171for mojomin changed_mojoms:
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7172 delta.append({
7173'filename': mojom.LocalPath(),
7174'old':'\n'.join(mojom.OldContents())orNone,
7175'new':'\n'.join(mojom.NewContents())orNone,
7176})
7177
7178 process= input_api.subprocess.Popen([
Takuto Ikutadca10222022-04-13 02:51:21[diff] [blame]7179 input_api.python3_executable,
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7180 input_api.os_path.join(
7181 input_api.PresubmitLocalPath(),'mojo','public','tools','mojom',
7182'check_stable_mojom_compatibility.py'),'--src-root',
7183 input_api.PresubmitLocalPath()
7184],
7185 stdin=input_api.subprocess.PIPE,
7186 stdout=input_api.subprocess.PIPE,
7187 stderr=input_api.subprocess.PIPE,
7188 universal_newlines=True)
7189(x, error)= process.communicate(input=input_api.json.dumps(delta))
7190if process.returncode:
7191return[
7192 output_api.PresubmitError(
7193'One or more [Stable] mojom definitions appears to have been changed '
Alex Goughc99921652024-02-15 22:59:12[diff] [blame]7194'in a way that is not backward-compatible. See '
7195'https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/public/tools/bindings/README.md#versioning'
7196' for details.',
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7197 long_text=error)
7198]
Erik Staabc734cd7a2021-11-23 03:11:52[diff] [blame]7199return[]
7200
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7201
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7202defCheckDeprecationOfPreferences(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7203"""Removing a preference should come with a deprecation."""
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7204
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7205defFilterFile(affected_file):
7206"""Accept only .cc files and the like."""
7207 file_inclusion_pattern=[r'.+%s'% _IMPLEMENTATION_EXTENSIONS]
7208 files_to_skip=(_EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
7209 input_api.DEFAULT_FILES_TO_SKIP)
7210return input_api.FilterSourceFile(
7211 affected_file,
7212 files_to_check=file_inclusion_pattern,
7213 files_to_skip=files_to_skip)
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7214
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7215defModifiedLines(affected_file):
7216"""Returns a list of tuples (line number, line text) of added and removed
7217 lines.
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7218
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7219 Deleted lines share the same line number as the previous line.
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7220
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7221 This relies on the scm diff output describing each changed code section
7222 with a line of the form
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7223
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7224 ^@@ <old line num>,<old size> <new line num>,<new size> @@$
7225 """
7226 line_num=0
7227 modified_lines=[]
7228for linein affected_file.GenerateScmDiff().splitlines():
7229# Extract <new line num> of the patch fragment (see format above).
7230 m= input_api.re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@',
7231 line)
7232if m:
7233 line_num= int(m.groups(1)[0])
7234continue
7235if((line.startswith('+')andnot line.startswith('++'))
7236or(line.startswith('-')andnot line.startswith('--'))):
7237 modified_lines.append((line_num, line))
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7238
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7239ifnot line.startswith('-'):
7240 line_num+=1
7241return modified_lines
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7242
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7243defFindLineWith(lines, needle):
7244"""Returns the line number (i.e. index + 1) in `lines` containing `needle`.
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7245
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7246 If 0 or >1 lines contain `needle`, -1 is returned.
7247 """
7248 matching_line_numbers=[
7249# + 1 for 1-based counting of line numbers.
7250 i+1for i, linein enumerate(lines)if needlein line
7251]
7252return matching_line_numbers[0]if len(
7253 matching_line_numbers)==1else-1
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7254
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7255defModifiedPrefMigration(affected_file):
7256"""Returns whether the MigrateObsolete.*Pref functions were modified."""
7257# Determine first and last lines of MigrateObsolete.*Pref functions.
7258 new_contents= affected_file.NewContents()
7259 range_1=(FindLineWith(new_contents,
7260'BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'),
7261FindLineWith(new_contents,
7262'END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'))
7263 range_2=(FindLineWith(new_contents,
7264'BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS'),
7265FindLineWith(new_contents,
7266'END_MIGRATE_OBSOLETE_PROFILE_PREFS'))
7267if(-1in range_1+ range_2):
7268raiseException(
7269'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.'
7270)
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7271
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7272# Check whether any of the modified lines are part of the
7273# MigrateObsolete.*Pref functions.
7274for line_nr, lineinModifiedLines(affected_file):
7275if(range_1[0]<= line_nr<= range_1[1]
7276or range_2[0]<= line_nr<= range_2[1]):
7277returnTrue
7278returnFalse
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7279
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7280 register_pref_pattern= input_api.re.compile(r'Register.+Pref')
7281 browser_prefs_file_pattern= input_api.re.compile(
7282 r'chrome/browser/prefs/browser_prefs.cc')
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7283
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7284 changes= input_api.AffectedFiles(include_deletes=True,
7285 file_filter=FilterFile)
7286 potential_problems=[]
7287for fin changes:
7288for linein f.GenerateScmDiff().splitlines():
7289# Check deleted lines for pref registrations.
7290if(line.startswith('-')andnot line.startswith('--')
7291and register_pref_pattern.search(line)):
7292 potential_problems.append('%s: %s'%(f.LocalPath(), line))
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7293
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7294if browser_prefs_file_pattern.search(f.LocalPath()):
7295# If the developer modified the MigrateObsolete.*Prefs() functions, we
7296# assume that they knew that they have to deprecate preferences and don't
7297# warn.
7298try:
7299ifModifiedPrefMigration(f):
7300return[]
7301exceptExceptionas e:
7302return[output_api.PresubmitError(str(e))]
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]7303
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7304if potential_problems:
7305return[
7306 output_api.PresubmitPromptWarning(
7307'Discovered possible removal of preference registrations.\n\n'
7308'Please make sure to properly deprecate preferences by clearing their\n'
7309'value for a couple of milestones before finally removing the code.\n'
7310'Otherwise data may stay in the preferences files forever. See\n'
7311'Migrate*Prefs() in chrome/browser/prefs/browser_prefs.cc and\n'
7312'chrome/browser/prefs/README.md for examples.\n'
7313'This may be a false positive warning (e.g. if you move preference\n'
7314'registrations to a different place).\n', potential_problems)
7315]
7316return[]
7317
Matt Stark6ef08872021-07-29 01:21:46[diff] [blame]7318
7319defCheckConsistentGrdChanges(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7320"""Changes to GRD files must be consistent for tools to read them."""
7321 changed_grds= input_api.AffectedFiles(
7322 include_deletes=False,
7323 file_filter=lambda f: f.LocalPath().endswith(('.grd')))
7324 errors=[]
7325 invalid_file_regexes=[(input_api.re.compile(matcher), msg)
7326for matcher, msgin _INVALID_GRD_FILE_LINE]
7327for grdin changed_grds:
7328for i, linein enumerate(grd.NewContents()):
7329for matcher, msgin invalid_file_regexes:
7330if matcher.search(line):
7331 errors.append(
7332 output_api.PresubmitError(
7333'Problem on {grd}:{i} - {msg}'.format(
7334 grd=grd.LocalPath(), i=i+1, msg=msg)))
7335return errors
7336
Kevin McNee967dd2d22021-11-15 16:09:29[diff] [blame]7337
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]7338defCheckAssertAshOnlyCode(input_api, output_api):
7339"""Errors if a BUILD.gn file in an ash/ directory doesn't include
Georg Neis94f87f02024-10-22 08:20:13[diff] [blame]7340 assert(is_chromeos).
7341 For a transition period, assert(is_chromeos_ash) is also accepted.
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]7342 """
7343
7344defFileFilter(affected_file):
7345"""Includes directories known to be Ash only."""
7346return input_api.FilterSourceFile(
7347 affected_file,
7348 files_to_check=(
7349 r'^ash/.*BUILD\.gn',# Top-level src/ash/.
7350 r'.*/ash/.*BUILD\.gn'),# Any path component.
7351 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP))
7352
7353 errors=[]
Georg Neis94f87f02024-10-22 08:20:13[diff] [blame]7354 pattern= input_api.re.compile(r'assert\(is_chromeos(_ash)?\b')
Jameson Thies0ce669f2021-12-09 15:56:56[diff] [blame]7355for fin input_api.AffectedFiles(include_deletes=False,
7356 file_filter=FileFilter):
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]7357if(not pattern.search(input_api.ReadFile(f))):
7358 errors.append(
7359 output_api.PresubmitError(
Georg Neis94f87f02024-10-22 08:20:13[diff] [blame]7360'Please add assert(is_chromeos) to %s. If that\'s not '
7361'possible, please create an issue and add a comment such '
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7362'as:\n # TODO(crbug.com/XXX): add '
Georg Neis94f87f02024-10-22 08:20:13[diff] [blame]7363'assert(is_chromeos) when ...'% f.LocalPath()))
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]7364return errors
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]7365
7366
Kalvin Lee84ad17a2023-09-25 11:14:41[diff] [blame]7367def_IsMiraclePtrDisallowed(input_api, affected_file):
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]7368 path= affected_file.UnixLocalPath()
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7369ifnot_IsCPlusPlusFile(input_api, path):
7370returnFalse
7371
Bartek Nowierski49b1a452024-06-08 00:24:35[diff] [blame]7372# Renderer-only code is generally allowed to use MiraclePtr. These
7373# directories, however, are specifically disallowed, for perf reasons.
Kalvin Lee84ad17a2023-09-25 11:14:41[diff] [blame]7374if("third_party/blink/renderer/core/"in path
7375or"third_party/blink/renderer/platform/heap/"in path
Bartek Nowierski49b1a452024-06-08 00:24:35[diff] [blame]7376or"third_party/blink/renderer/platform/wtf/"in path
7377or"third_party/blink/renderer/platform/fonts/"in path):
7378returnTrue
7379
7380# The below paths are an explicitly listed subset of Renderer-only code,
7381# because the plan is to Oilpanize it.
7382# TODO(crbug.com/330759291): Remove once Oilpanization is completed or
7383# abandoned.
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7384if("third_party/blink/renderer/core/paint/"in pathor
7385"third_party/blink/renderer/platform/graphics/compositing/"in path
Bartek Nowierski49b1a452024-06-08 00:24:35[diff] [blame]7386or"third_party/blink/renderer/platform/graphics/paint/"in path):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7387returnTrue
7388
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7389# We assume that everything else may be used outside of Renderer processes.
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]7390returnFalse
7391
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7392
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7393# TODO(crbug.com/40206238): Remove these checks, once they are replaced
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]7394# by the Chromium Clang Plugin (which will be preferable because it will
7395# 1) report errors earlier - at compile-time and 2) cover more rules).
7396defCheckRawPtrUsage(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7397"""Rough checks that raw_ptr<T> usage guidelines are followed."""
7398 errors=[]
7399# The regex below matches "raw_ptr<" following a word boundary, but not in a
7400# C++ comment.
7401 raw_ptr_matcher= input_api.re.compile(r'^((?!//).)*\braw_ptr<')
Kalvin Lee84ad17a2023-09-25 11:14:41[diff] [blame]7402 file_filter=lambda f:_IsMiraclePtrDisallowed(input_api, f)
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7403for f, line_num, linein input_api.RightHandSideLines(file_filter):
7404if raw_ptr_matcher.search(line):
7405 errors.append(
7406 output_api.PresubmitError(
7407'Problem on {path}:{line} - '\
Kalvin Lee84ad17a2023-09-25 11:14:41[diff] [blame]7408'raw_ptr<T> should not be used in this renderer code '\
Sam Maiera6e76d72022-02-11 21:43:50[diff] [blame]7409'(as documented in the "Pointers to unprotected memory" '\
7410'section in //base/memory/raw_ptr.md)'.format(
7411 path=f.LocalPath(), line=line_num)))
7412return errors
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]7413
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7414
mikt9337567c2023-09-08 18:38:17[diff] [blame]7415defCheckAdvancedMemorySafetyChecksUsage(input_api, output_api):
7416"""Checks that ADVANCED_MEMORY_SAFETY_CHECKS() macro is neither added nor
7417 removed as it is managed by the memory safety team internally.
7418 Do not add / remove it manually."""
7419 paths= set([])
7420# The regex below matches "ADVANCED_MEMORY_SAFETY_CHECKS(" following a word
7421# boundary, but not in a C++ comment.
7422 macro_matcher= input_api.re.compile(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7423 r'^((?!//).)*\bADVANCED_MEMORY_SAFETY_CHECKS\(',
7424 input_api.re.MULTILINE)
mikt9337567c2023-09-08 18:38:17[diff] [blame]7425for fin input_api.AffectedFiles():
7426ifnot_IsCPlusPlusFile(input_api, f.LocalPath()):
7427continue
7428if macro_matcher.search(f.GenerateScmDiff()):
7429 paths.add(f.LocalPath())
7430ifnot paths:
7431return[]
7432return[output_api.PresubmitPromptWarning(
7433'ADVANCED_MEMORY_SAFETY_CHECKS() macro is managed by ' \
7434'the memory safety team (chrome-memory-safety@). ' \
7435'Please contact us to add/delete the uses of the macro.',
7436 paths)]
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]7437
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7438
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]7439defCheckPythonShebang(input_api, output_api):
7440"""Checks that python scripts use #!/usr/bin/env instead of hardcoding a
7441 system-wide python.
7442 """
7443 errors=[]
7444 sources=lambda affected_file: input_api.FilterSourceFile(
7445 affected_file,
7446 files_to_skip=((_THIRD_PARTY_EXCEPT_BLINK,
7447 r'third_party/blink/web_tests/external/')+ input_api.
7448 DEFAULT_FILES_TO_SKIP),
7449 files_to_check=[r'.*\.py$'])
7450for fin input_api.AffectedSourceFiles(sources):
Takuto Ikuta36976512021-11-30 23:15:27[diff] [blame]7451for line_num, linein f.ChangedContents():
7452if line_num==1and line.startswith('#!/usr/bin/python'):
7453 errors.append(f.LocalPath())
7454break
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]7455
7456 result=[]
7457for filein errors:
7458 result.append(
7459 output_api.PresubmitError(
7460"Please use '#!/usr/bin/env python/2/3' as the shebang of %s"%
7461 file))
7462return result
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7463
7464
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7465defCheckAndroidTestAnnotations(input_api, output_api):
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7466"""Checks that tests have either @Batch or @DoNotBatch annotation. If this
7467 is not an instrumentation test, disregard."""
7468
7469 batch_annotation= input_api.re.compile(r'^\s*@Batch')
7470 do_not_batch_annotation= input_api.re.compile(r'^\s*@DoNotBatch')
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7471 robolectric_test= input_api.re.compile(
7472 r'@RunWith\((.*?)RobolectricTestRunner')
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7473 test_class_declaration= input_api.re.compile(r'^\s*public\sclass.*Test')
7474 uiautomator_test= input_api.re.compile(r'[uU]i[aA]utomator')
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7475 test_annotation_declaration= input_api.re.compile(
7476 r'^\s*public\s@interface\s.*{')
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7477
ckitagawae8fd23b2022-06-17 15:29:38[diff] [blame]7478 missing_annotation_errors=[]
7479 extra_annotation_errors=[]
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7480 wrong_robolectric_test_runner_errors=[]
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7481
7482def_FilterFile(affected_file):
7483return input_api.FilterSourceFile(
7484 affected_file,
7485 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP,
7486 files_to_check=[r'.*Test\.java$'])
7487
7488for fin input_api.AffectedSourceFiles(_FilterFile):
7489 batch_matched=None
7490 do_not_batch_matched=None
7491 is_instrumentation_test=True
Mark Schillaci8ef0d872023-07-18 22:07:59[diff] [blame]7492 test_annotation_declaration_matched=None
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7493 has_base_robolectric_rule=False
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7494for linein f.NewContents():
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7495if'BaseRobolectricTestRule'in line:
7496 has_base_robolectric_rule=True
7497continue
7498if m:= robolectric_test.search(line):
7499 is_instrumentation_test=False
7500if m.group(1)==''andnot has_base_robolectric_rule:
Yiwei Zhang5341bf02025-03-20 16:34:13[diff] [blame]7501 path= str(f.LocalPath())
7502# These two spots cannot use it.
7503if'webapk'notin pathand'build'notin path:
7504 wrong_robolectric_test_runner_errors.append(path)
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7505break
7506if uiautomator_test.search(line):
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7507 is_instrumentation_test=False
7508break
7509ifnot batch_matched:
7510 batch_matched= batch_annotation.search(line)
7511ifnot do_not_batch_matched:
7512 do_not_batch_matched= do_not_batch_annotation.search(line)
7513 test_class_declaration_matched= test_class_declaration.search(
7514 line)
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7515 test_annotation_declaration_matched= test_annotation_declaration.search(
7516 line)
Mark Schillaci8ef0d872023-07-18 22:07:59[diff] [blame]7517if test_class_declaration_matchedor test_annotation_declaration_matched:
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7518break
Mark Schillaci8ef0d872023-07-18 22:07:59[diff] [blame]7519if test_annotation_declaration_matched:
7520continue
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7521if(is_instrumentation_testandnot batch_matched
7522andnot do_not_batch_matched):
Sam Maier4cef9242022-10-03 14:21:24[diff] [blame]7523 missing_annotation_errors.append(str(f.LocalPath()))
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7524if(not is_instrumentation_test
7525and(batch_matchedor do_not_batch_matched)):
Sam Maier4cef9242022-10-03 14:21:24[diff] [blame]7526 extra_annotation_errors.append(str(f.LocalPath()))
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7527
7528 results=[]
7529
ckitagawae8fd23b2022-06-17 15:29:38[diff] [blame]7530if missing_annotation_errors:
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7531 results.append(
7532 output_api.PresubmitPromptWarning(
7533"""
Andrew Grieve43a5cf82023-09-08 15:09:46[diff] [blame]7534A change was made to an on-device test that has neither been annotated with
7535@Batch nor @DoNotBatch. If this is a new test, please add the annotation. If
7536this is an existing test, please consider adding it if you are sufficiently
7537familiar with the test (but do so as a separate change).
7538
Jens Mueller2085ff82023-02-27 11:54:49[diff] [blame]7539See https://source.chromium.org/chromium/chromium/src/+/main:docs/testing/batching_instrumentation_tests.md
ckitagawae8fd23b2022-06-17 15:29:38[diff] [blame]7540""", missing_annotation_errors))
7541if extra_annotation_errors:
7542 results.append(
7543 output_api.PresubmitPromptWarning(
7544"""
7545Robolectric tests do not need a @Batch or @DoNotBatch annotations.
7546""", extra_annotation_errors))
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7547if wrong_robolectric_test_runner_errors:
7548 results.append(
7549 output_api.PresubmitPromptWarning(
7550"""
Wenyu Fu0005ab82025-01-03 18:13:26[diff] [blame]7551Robolectric tests should use either @RunWith(BaseRobolectricTestRunner.class) (or
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]7552a subclass of it), or use "@Rule BaseRobolectricTestRule".
7553""", wrong_robolectric_test_runner_errors))
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]7554
7555return results
Sam Maier4cef9242022-10-03 14:21:24[diff] [blame]7556
7557
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]7558def_CheckAndroidNullAwayAnnotatedClasses(input_api, output_api):
7559"""Checks that Java classes/interfaces/annotations are null-annotated."""
7560
Henrique Nakashima2bdd8ad2025-04-08 18:24:57[diff] [blame]7561# Temporary, crbug.com/389129271
7562if input_api.change.RepositoryRoot().endswith('clank'):
7563return[]
7564
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7565 nullmarked_annotation= input_api.re.compile(
7566 r'^\s*@(NullMarked|NullUnmarked)')
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]7567
7568 missing_annotation_errors=[]
7569
7570def_FilterFile(affected_file):
7571return input_api.FilterSourceFile(
7572 affected_file,
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7573 files_to_skip=(
7574 _EXCLUDED_PATHS+ _TEST_CODE_EXCLUDED_PATHS+
7575 input_api.DEFAULT_FILES_TO_SKIP+(
7576 r'.*Test.*\.java',
7577 r'^android_webview/.*',# Temporary, crbug.com/389129271
7578 r'^build/.*',
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7579 r'^chromecast/.*',
7580 r'^components/cronet/.*',
7581 r'^tools/.*',
7582)),
7583 files_to_check=[r'.*\.java$'])
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]7584
7585for fin input_api.AffectedSourceFiles(_FilterFile):
Henrique Nakashimac6605432025-04-24 18:11:59[diff] [blame]7586if f.Action()!='A':
7587continue
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]7588for linein f.NewContents():
7589if nullmarked_annotation.search(line):
7590break
7591else:
7592 missing_annotation_errors.append(str(f.LocalPath()))
7593
7594 results=[]
7595
7596if missing_annotation_errors:
7597 results.append(
Henrique Nakashima8bafbc52025-04-22 19:38:42[diff] [blame]7598 output_api.PresubmitError(
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]7599"""
7600Please add @NullMarked and fix the NullAway warnings in the following files
7601(see https://chromium.googlesource.com/chromium/src/+/main/styleguide/java/nullaway.md):
7602""", missing_annotation_errors))
7603
7604return results
7605
7606
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7607defCheckNoJsInIos(input_api, output_api):
7608"""Checks to make sure that JavaScript files are not used on iOS."""
7609
7610def_FilterFile(affected_file):
7611return input_api.FilterSourceFile(
7612 affected_file,
7613 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP+
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7614(r'^ios/third_party/*', r'^ios/tools/*', r'^third_party/*',
7615 r'^components/autofill/ios/form_util/resources/*'),
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7616 files_to_check=[r'^ios/.*\.js$', r'.*/ios/.*\.js$'])
7617
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7618 deleted_files=[]
7619
7620# Collect filenames of all removed JS files.
Arthur Sonzognic66e9c82024-04-23 07:53:04[diff] [blame]7621for fin input_api.AffectedFiles(file_filter=_FilterFile):
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7622 local_path= f.LocalPath()
7623
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7624if input_api.os_path.splitext(
7625 local_path)[1]=='.js'and f.Action()=='D':
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7626 deleted_files.append(input_api.os_path.basename(local_path))
7627
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7628 error_paths=[]
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7629 moved_paths=[]
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7630 warning_paths=[]
7631
7632for fin input_api.AffectedSourceFiles(_FilterFile):
7633 local_path= f.LocalPath()
7634
7635if input_api.os_path.splitext(local_path)[1]=='.js':
7636if f.Action()=='A':
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7637if input_api.os_path.basename(local_path)in deleted_files:
7638# This script was probably moved rather than newly created.
7639# Present a warning instead of an error for these cases.
7640 moved_paths.append(local_path)
7641else:
7642 error_paths.append(local_path)
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7643elif f.Action()!='D':
7644 warning_paths.append(local_path)
7645
7646 results=[]
7647
7648if warning_paths:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7649 results.append(
7650 output_api.PresubmitPromptWarning(
7651'TypeScript is now fully supported for iOS feature scripts. '
7652'Consider converting JavaScript files to TypeScript. See '
7653'//ios/web/public/js_messaging/README.md for more details.',
7654 warning_paths))
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7655
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7656if moved_paths:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7657 results.append(
7658 output_api.PresubmitPromptWarning(
7659'Do not use JavaScript on iOS for new files as TypeScript is '
7660'fully supported. (If this is a moved file, you may leave the '
7661'script unconverted.) See //ios/web/public/js_messaging/README.md '
7662'for help using scripts on iOS.', moved_paths))
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]7663
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7664if error_paths:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7665 results.append(
7666 output_api.PresubmitError(
7667'Do not use JavaScript on iOS as TypeScript is fully supported. '
7668'See //ios/web/public/js_messaging/README.md for help using '
7669'scripts on iOS.', error_paths))
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]7670
7671return results
Hans Wennborg23a81d52023-03-24 16:38:13[diff] [blame]7672
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7673
Hans Wennborg23a81d52023-03-24 16:38:13[diff] [blame]7674defCheckLibcxxRevisionsMatch(input_api, output_api):
7675"""Check to make sure the libc++ version matches across deps files."""
Andrew Grieve21bb6792023-03-27 19:06:48[diff] [blame]7676# Disable check for changes to sub-repositories.
7677if input_api.PresubmitLocalPath()!= input_api.change.RepositoryRoot():
Sam Maierb926c58c2023-08-08 19:58:25[diff] [blame]7678return[]
Hans Wennborg23a81d52023-03-24 16:38:13[diff] [blame]7679
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7680 DEPS_FILES=['DEPS','buildtools/deps_revisions.gni']
Hans Wennborg23a81d52023-03-24 16:38:13[diff] [blame]7681
Anton Bershanskyi4253349482025-02-11 21:01:27[diff] [blame]7682 file_filter=lambda f: f.UnixLocalPath()in DEPS_FILES
Hans Wennborg23a81d52023-03-24 16:38:13[diff] [blame]7683 changed_deps_files= input_api.AffectedFiles(file_filter=file_filter)
7684ifnot changed_deps_files:
7685return[]
7686
7687defLibcxxRevision(file):
7688 file= input_api.os_path.join(input_api.PresubmitLocalPath(),
7689*file.split('/'))
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7690return input_api.re.search(r'libcxx_revision.*[:=].*[\'"](\w+)[\'"]',
7691 input_api.ReadFile(file)).group(1)
Hans Wennborg23a81d52023-03-24 16:38:13[diff] [blame]7692
7693if len(set([LibcxxRevision(f)for fin DEPS_FILES]))==1:
7694return[]
7695
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7696return[
7697 output_api.PresubmitError(
7698'libcxx_revision not equal across %s'%', '.join(DEPS_FILES),
7699 changed_deps_files)
7700]
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]7701
7702
7703defCheckDanglingUntriaged(input_api, output_api):
7704"""Warn developers adding DanglingUntriaged raw_ptr."""
7705
7706# Ignore during git presubmit --all.
7707#
7708# This would be too costly, because this would check every lines of every
7709# C++ files. Check from _BANNED_CPP_FUNCTIONS are also reading the whole
7710# source code, but only once to apply every checks. It seems the bots like
7711# `win-presubmit` are particularly sensitive to reading the files. Adding
7712# this check caused the bot to run 2x longer. See https://crbug.com/1486612.
7713if input_api.no_diffs:
Arthur Sonzogni9eafd222023-11-10 08:50:39[diff] [blame]7714return[]
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]7715
7716defFilterFile(file):
7717return input_api.FilterSourceFile(
7718 file,
7719 files_to_check=[r".*\.(h|cc|cpp|cxx|m|mm)$"],
7720 files_to_skip=[r"^base/allocator.*"],
7721)
7722
7723 count=0
Arthur Sonzognic66e9c82024-04-23 07:53:04[diff] [blame]7724for fin input_api.AffectedFiles(file_filter=FilterFile):
Arthur Sonzogni9eafd222023-11-10 08:50:39[diff] [blame]7725 count-= sum([l.count("DanglingUntriaged")for lin f.OldContents()])
7726 count+= sum([l.count("DanglingUntriaged")for lin f.NewContents()])
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]7727
7728# Most likely, nothing changed:
7729if count==0:
7730return[]
7731
7732# Congrats developers for improving it:
7733if count<0:
Arthur Sonzogni9eafd222023-11-10 08:50:39[diff] [blame]7734 message= f"DanglingUntriaged pointers removed: {-count}\nThank you!"
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]7735return[output_api.PresubmitNotifyResult(message)]
7736
7737# Check for 'DanglingUntriaged-notes' in the description:
7738 notes_regex= input_api.re.compile("DanglingUntriaged-notes[:=]")
7739if any(
7740 notes_regex.match(line)
7741for linein input_api.change.DescriptionText().splitlines()):
7742return[]
7743
7744# Check for DanglingUntriaged-notes in the git footer:
7745if input_api.change.GitFootersFromDescription().get(
7746"DanglingUntriaged-notes",[]):
7747return[]
7748
7749 message=(
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7750"Unexpected new occurrences of `DanglingUntriaged` detected. Please\n"
7751+"avoid adding new ones\n"+"\n"+"See documentation:\n"+
7752"https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md\n"
7753+"\n"+"See also the guide to fix dangling pointers:\n"+
7754"https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr_guide.md\n"
7755+"\n"+
Arthur Sonzogni9eafd222023-11-10 08:50:39[diff] [blame]7756"To disable this warning, please add in the commit description:\n"+
Alex Gough26dcd852023-12-22 16:47:19[diff] [blame]7757"DanglingUntriaged-notes: <rationale for new untriaged dangling "+
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7758"pointers>")
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]7759return[output_api.PresubmitPromptWarning(message)]
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]7760
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7761
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]7762defCheckInlineConstexprDefinitionsInHeaders(input_api, output_api):
7763"""Checks that non-static constexpr definitions in headers are inline."""
7764# In a properly formatted file, constexpr definitions inside classes or
7765# structs will have additional whitespace at the beginning of the line.
7766# The pattern looks for variables initialized as constexpr kVar = ...; or
7767# constexpr kVar{...};
7768# The pattern does not match expressions that have braces in kVar to avoid
7769# matching constexpr functions.
7770 pattern= input_api.re.compile(r'^constexpr (?!inline )[^\(\)]*[={]')
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7771 attribute_pattern= input_api.re.compile(
7772 r'(\[\[[a-zA-Z_:]+\]\]|[A-Z]+[A-Z_]+) ')
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]7773 problems=[]
7774for fin input_api.AffectedFiles():
7775ifnot_IsCPlusPlusHeaderFile(input_api, f.LocalPath()):
7776continue
7777
7778for line_number, linein f.ChangedContents():
7779 line= attribute_pattern.sub('', line)
7780if pattern.search(line):
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7781 problems.append(f"{f.LocalPath()}: {line_number}\n {line}")
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]7782
7783if problems:
7784return[
7785 output_api.PresubmitPromptWarning(
7786'Consider inlining constexpr variable definitions in headers '
7787'outside of classes to avoid unnecessary copies of the '
7788'constant. See https://abseil.io/tips/168 for more details.',
7789 problems)
7790]
7791else:
7792return[]
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7793
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7794
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7795defCheckTodoBugReferences(input_api, output_api):
7796"""Checks that bugs in TODOs use updated issue tracker IDs."""
7797
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7798 files_to_skip=[
7799'PRESUBMIT_test.py', r"^third_party/rust/chromium_crates_io/vendor/.*"
7800]
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7801
7802def_FilterFile(affected_file):
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7803return input_api.FilterSourceFile(affected_file,
7804 files_to_skip=files_to_skip)
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7805
7806# Monorail bug IDs are all less than or equal to 1524553 so check that all
7807# bugs in TODOs are greater than that value.
Tom Sepez8e628582025-02-14 02:18:55[diff] [blame]7808 pattern= input_api.re.compile(r'.*\bTODO\([^\)0-9]*([0-9]+)\).*')
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7809 problems=[]
7810for fin input_api.AffectedSourceFiles(_FilterFile):
7811for line_number, linein f.ChangedContents():
7812 match= pattern.match(line)
7813if matchand int(match.group(1))<=1524553:
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7814 problems.append(f"{f.LocalPath()}: {line_number}\n {line}")
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7815
7816if problems:
7817return[
7818 output_api.PresubmitPromptWarning(
Alison Galecb598de52024-04-26 17:03:25[diff] [blame]7819'TODOs should use the new Chromium Issue Tracker IDs which can '
7820'be found by navigating to the bug. See '
Daniel Cheng6303eed2025-05-03 00:12:33[diff] [blame]7821'https://crbug.com/336778624 for more details.', problems)
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]7822]
7823else:
7824return[]
Mikita Kuchyne9cd0e29f2025-05-26 11:47:25[diff] [blame]7825
7826defCheckNoBrowserStarInUnittests(input_api, output_api):
7827"""Checks that unit-tests don't contain Browser* variables.
7828 """
7829 problems=[]
7830
7831defFileFilter(affected_file):
7832"""Check unit-tests only"""
7833return input_api.FilterSourceFile(
7834 affected_file,
7835 files_to_check=(
7836 r'.*unittest\.cc$',
7837 r'.*unittest\.h$'
7838),
7839 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP,
7840)
7841
7842 browser_star_pattern= input_api.re.compile(r'\bBrowser\s*\*')
7843
7844for fin input_api.AffectedFiles(include_deletes=False,
7845 file_filter=FileFilter):
7846for line_num, linein f.ChangedContents():
7847 match= browser_star_pattern.search(line)
7848if match:
7849 problems.append(' %s:%d:%s'%
7850(f.LocalPath(), line_num, match.group(0)))
7851
7852ifnot problems:
7853return[]
7854
7855 WARNING_MSG="""Do not use "Browser*" type in unittest files (e.g.,
7856 "*unittest.cc" or "*unittest.h"). Unit tests should generally
7857 not depend on the full Browser class or related components. Consider
7858 refactoring to mock dependencies, use test-specific fakes,
7859 or determine if a browser_test is more appropriate.
7860 """
7861return[output_api.PresubmitPromptWarning(WARNING_MSG, items=problems)]

[8]ページ先頭

©2009-2025 Movatter.jp