blob: f5972ccb395e8717c6ac46f0ce3d39181e4ba647 [file] [log] [blame]
Avi Drissman24976592022-09-12 15:24:311# Copyright 2012 The Chromium Authors
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
Daniel Chengd88244472022-05-16 09:08:477See https://www.chromium.org/developers/how-tos/depottools/presubmit-scripts/
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
Daniel Chenga44a1bcd2022-03-15 20:00:1510
Daniel Chenga37c03db2022-05-12 17:20:3411from typing import Callable
Daniel Chenga44a1bcd2022-03-15 20:00:1512from typing import Optional
13from typing import Sequence
14from dataclasses import dataclass
15
Saagar Sanghavifceeaae2020-08-12 16:40:3616PRESUBMIT_VERSION = '2.0.0'
[email protected]eea609a2011-11-18 13:10:1217
Dirk Prankee3c9c62d2021-05-18 18:35:5918
[email protected]379e7dd2010-01-28 17:39:2119_EXCLUDED_PATHS = (
Bruce Dawson7f8566b2022-05-06 16:22:1820 # Generated file
Bruce Dawson40fece62022-09-16 19:58:3121 (r"chrome/android/webapk/shell_apk/src/org/chromium"
22 r"/webapk/lib/runtime_library/IWebApkApi.java"),
Mila Greene3aa7222021-09-07 16:34:0823 # File needs to write to stdout to emulate a tool it's replacing.
Bruce Dawson40fece62022-09-16 19:58:3124 r"chrome/updater/mac/keystone/ksadmin.mm",
Ilya Shermane8a7d2d2020-07-25 04:33:4725 # Generated file.
Bruce Dawson40fece62022-09-16 19:58:3126 (r"^components/variations/proto/devtools/"
Ilya Shermanc167a962020-08-18 18:40:2627 r"client_variations.js"),
Bruce Dawson3bd976c2022-05-06 22:47:5228 # These are video files, not typescript.
Bruce Dawson40fece62022-09-16 19:58:3129 r"^media/test/data/.*.ts",
30 r"^native_client_sdksrc/build_tools/make_rules.py",
31 r"^native_client_sdk/src/build_tools/make_simple.py",
32 r"^native_client_sdk/src/tools/.*.mk",
33 r"^net/tools/spdyshark/.*",
34 r"^skia/.*",
35 r"^third_party/blink/.*",
36 r"^third_party/breakpad/.*",
Darwin Huangd74a9d32019-07-17 17:58:4637 # sqlite is an imported third party dependency.
Bruce Dawson40fece62022-09-16 19:58:3138 r"^third_party/sqlite/.*",
39 r"^v8/.*",
[email protected]3e4eb112011-01-18 03:29:5440 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5341 r".+_autogen\.h$",
Yue Shecf1380552022-08-23 20:59:2042 r".+_pb2(_grpc)?\.py$",
Bruce Dawson40fece62022-09-16 19:58:3143 r".+/pnacl_shim\.c$",
44 r"^gpu/config/.*_list_json\.cc$",
45 r"tools/md_browser/.*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1446 # Test pages for Maps telemetry tests.
Bruce Dawson40fece62022-09-16 19:58:3147 r"tools/perf/page_sets/maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5448 # Test pages for WebRTC telemetry tests.
Bruce Dawson40fece62022-09-16 19:58:3149 r"tools/perf/page_sets/webrtc_cases.*",
dpapad2efd4452023-04-06 01:43:4550 # Test file compared with generated output.
51 r"tools/polymer/tests/html_to_wrapper/.*.html.ts$",
[email protected]4306417642009-06-11 00:33:4052)
[email protected]ca8d1982009-02-19 16:33:1253
John Abd-El-Malek759fea62021-03-13 03:41:1454_EXCLUDED_SET_NO_PARENT_PATHS = (
55 # It's for historical reasons that blink isn't a top level directory, where
56 # it would be allowed to have "set noparent" to avoid top level owners
57 # accidentally +1ing changes.
58 'third_party/blink/OWNERS',
59)
60
wnwenbdc444e2016-05-25 13:44:1561
[email protected]06e6d0ff2012-12-11 01:36:4462# Fragment of a regular expression that matches C++ and Objective-C++
63# implementation files.
64_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
65
wnwenbdc444e2016-05-25 13:44:1566
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1967# Fragment of a regular expression that matches C++ and Objective-C++
68# header files.
69_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
70
71
Aleksey Khoroshilov9b28c032022-06-03 16:35:3272# Paths with sources that don't use //base.
73_NON_BASE_DEPENDENT_PATHS = (
Bruce Dawson40fece62022-09-16 19:58:3174 r"^chrome/browser/browser_switcher/bho/",
75 r"^tools/win/",
Aleksey Khoroshilov9b28c032022-06-03 16:35:3276)
77
78
[email protected]06e6d0ff2012-12-11 01:36:4479# Regular expression that matches code only used for test binaries
80# (best effort).
81_TEST_CODE_EXCLUDED_PATHS = (
Bruce Dawson40fece62022-09-16 19:58:3182 r'.*/(fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
Marijn Kruisselbrink2a2d5fc2024-05-15 15:23:4983 # Test support files, like:
84 # foo_test_support.cc
85 # bar_test_util_linux.cc (suffix)
86 # baz_test_base.cc
87 r'.+_test_(base|support|util)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
James Cook1b4dc132021-03-09 22:45:1388 # Test suite files, like:
89 # foo_browsertest.cc
90 # bar_unittest_mac.cc (suffix)
91 # baz_unittests.cc (plural)
92 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(s)?(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1293 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1894 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
Victor Hugo Vianna Silvac22e0202021-06-09 19:46:2195 r'.+sync_service_impl_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Bruce Dawson40fece62022-09-16 19:58:3196 r'.*/(test|tool(s)?)/.*',
danakj89f47082020-09-02 17:53:4397 # content_shell is used for running content_browsertests.
Bruce Dawson40fece62022-09-16 19:58:3198 r'content/shell/.*',
danakj89f47082020-09-02 17:53:4399 # Web test harness.
Bruce Dawson40fece62022-09-16 19:58:31100 r'content/web_test/.*',
[email protected]7b054982013-11-27 00:44:47101 # Non-production example code.
Bruce Dawson40fece62022-09-16 19:58:31102 r'mojo/examples/.*',
[email protected]8176de12014-06-20 19:07:08103 # Launcher for running iOS tests on the simulator.
Bruce Dawson40fece62022-09-16 19:58:31104 r'testing/iossim/iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:41105 # EarlGrey app side code for tests.
Bruce Dawson40fece62022-09-16 19:58:31106 r'ios/.*_app_interface\.mm$',
Allen Bauer0678d772020-05-11 22:25:17107 # Views Examples code
Bruce Dawson40fece62022-09-16 19:58:31108 r'ui/views/examples/.*',
Austin Sullivan33da70a2020-10-07 15:39:41109 # Chromium Codelab
Bruce Dawson40fece62022-09-16 19:58:31110 r'codelabs/*'
[email protected]06e6d0ff2012-12-11 01:36:44111)
[email protected]ca8d1982009-02-19 16:33:12112
Daniel Bratell609102be2019-03-27 20:53:21113_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:15114
[email protected]eea609a2011-11-18 13:10:12115_TEST_ONLY_WARNING = (
116 'You might be calling functions intended only for testing from\n'
danakj5f6e3b82020-09-10 13:52:55117 'production code. If you are doing this from inside another method\n'
118 'named as *ForTesting(), then consider exposing things to have tests\n'
119 'make that same call directly.\n'
120 'If that is not possible, you may put a comment on the same line with\n'
121 ' // IN-TEST \n'
122 'to tell the PRESUBMIT script that the code is inside a *ForTesting()\n'
123 'method and can be ignored. Do not do this inside production code.\n'
124 'The android-binary-size trybot will block if the method exists in the\n'
Yulun Zeng08d7d8c2024-02-01 18:46:54125 'release apk.\n'
126 'Note: this warning might be a false positive (crbug.com/1196548).')
[email protected]eea609a2011-11-18 13:10:12127
128
Daniel Chenga44a1bcd2022-03-15 20:00:15129@dataclass
130class BanRule:
Daniel Chenga37c03db2022-05-12 17:20:34131 # String pattern. If the pattern begins with a slash, the pattern will be
132 # treated as a regular expression instead.
133 pattern: str
134 # Explanation as a sequence of strings. Each string in the sequence will be
135 # printed on its own line.
136 explanation: Sequence[str]
137 # Whether or not to treat this ban as a fatal error. If unspecified,
138 # defaults to true.
139 treat_as_error: Optional[bool] = None
140 # Paths that should be excluded from the ban check. Each string is a regular
141 # expression that will be matched against the path of the file being checked
142 # relative to the root of the source tree.
143 excluded_paths: Optional[Sequence[str]] = None
[email protected]cf9b78f2012-11-14 11:40:28144
Daniel Chenga44a1bcd2022-03-15 20:00:15145
Daniel Cheng917ce542022-03-15 20:46:57146_BANNED_JAVA_IMPORTS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15147 BanRule(
148 'import java.net.URI;',
149 (
150 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
151 ),
152 excluded_paths=(
153 (r'net/android/javatests/src/org/chromium/net/'
154 'AndroidProxySelectorTest\.java'),
155 r'components/cronet/',
156 r'third_party/robolectric/local/',
157 ),
Michael Thiessen44457642020-02-06 00:24:15158 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15159 BanRule(
160 'import android.annotation.TargetApi;',
161 (
162 'Do not use TargetApi, use @androidx.annotation.RequiresApi instead. '
163 'RequiresApi ensures that any calls are guarded by the appropriate '
164 'SDK_INT check. See https://crbug.com/1116486.',
165 ),
166 ),
167 BanRule(
Mohamed Heikal3d7a94c2023-03-28 16:55:24168 'import androidx.test.rule.UiThreadTestRule;',
Daniel Chenga44a1bcd2022-03-15 20:00:15169 (
170 'Do not use UiThreadTestRule, just use '
171 '@org.chromium.base.test.UiThreadTest on test methods that should run '
172 'on the UI thread. See https://crbug.com/1111893.',
173 ),
174 ),
175 BanRule(
Mohamed Heikal3d7a94c2023-03-28 16:55:24176 'import androidx.test.annotation.UiThreadTest;',
177 ('Do not use androidx.test.annotation.UiThreadTest, use '
Daniel Chenga44a1bcd2022-03-15 20:00:15178 'org.chromium.base.test.UiThreadTest instead. See '
179 'https://crbug.com/1111893.',
180 ),
181 ),
182 BanRule(
Mohamed Heikal3d7a94c2023-03-28 16:55:24183 'import androidx.test.rule.ActivityTestRule;',
Daniel Chenga44a1bcd2022-03-15 20:00:15184 (
185 'Do not use ActivityTestRule, use '
186 'org.chromium.base.test.BaseActivityTestRule instead.',
187 ),
188 excluded_paths=(
189 'components/cronet/',
190 ),
191 ),
Min Qinbc44383c2023-02-22 17:25:26192 BanRule(
193 'import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;',
194 (
195 'Do not use VectorDrawableCompat, use getResources().getDrawable() to '
196 'avoid extra indirections. Please also add trace event as the call '
197 'might take more than 20 ms to complete.',
198 ),
199 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15200)
wnwenbdc444e2016-05-25 13:44:15201
Daniel Cheng917ce542022-03-15 20:46:57202_BANNED_JAVA_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15203 BanRule(
Eric Stevensona9a980972017-09-23 00:04:41204 'StrictMode.allowThreadDiskReads()',
205 (
206 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
207 'directly.',
208 ),
209 False,
210 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15211 BanRule(
Eric Stevensona9a980972017-09-23 00:04:41212 'StrictMode.allowThreadDiskWrites()',
213 (
214 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
215 'directly.',
216 ),
217 False,
218 ),
Daniel Cheng917ce542022-03-15 20:46:57219 BanRule(
Michael Thiessen0f2547e2020-07-27 21:55:36220 '.waitForIdleSync()',
221 (
222 'Do not use waitForIdleSync as it masks underlying issues. There is '
223 'almost always something else you should wait on instead.',
224 ),
225 False,
226 ),
Ashley Newson09cbd602022-10-26 11:40:14227 BanRule(
Ashley Newsoneb6f5ce2022-10-26 14:45:42228 r'/(?<!\bsuper\.)(?<!\bIntent )\bregisterReceiver\(',
Ashley Newson09cbd602022-10-26 11:40:14229 (
230 'Do not call android.content.Context.registerReceiver (or an override) '
231 'directly. Use one of the wrapper methods defined in '
232 'org.chromium.base.ContextUtils, such as '
233 'registerProtectedBroadcastReceiver, '
234 'registerExportedBroadcastReceiver, or '
235 'registerNonExportedBroadcastReceiver. See their documentation for '
236 'which one to use.',
237 ),
238 True,
239 excluded_paths=(
Ashley Newson22bc26d2022-11-01 20:30:57240 r'.*Test[^a-z]',
241 r'third_party/',
Ashley Newson09cbd602022-10-26 11:40:14242 'base/android/java/src/org/chromium/base/ContextUtils.java',
Brandon Mousseau7e76a9c2022-12-08 22:08:38243 'chromecast/browser/android/apk/src/org/chromium/chromecast/shell/BroadcastReceiverScope.java',
Ashley Newson09cbd602022-10-26 11:40:14244 ),
245 ),
Ted Chocd5b327b12022-11-05 02:13:22246 BanRule(
247 r'/(?:extends|new)\s*(?:android.util.)?Property<[A-Za-z.]+,\s*(?:Integer|Float)>',
248 (
249 'Do not use Property<..., Integer|Float>, but use FloatProperty or '
250 'IntProperty because it will avoid unnecessary autoboxing of '
251 'primitives.',
252 ),
253 ),
Peilin Wangbba4a8652022-11-10 16:33:57254 BanRule(
255 'requestLayout()',
256 (
257 'Layouts can be expensive. Prefer using ViewUtils.requestLayout(), '
258 'which emits a trace event with additional information to help with '
259 'scroll jank investigations. See http://crbug.com/1354176.',
260 ),
261 False,
262 excluded_paths=(
263 'ui/android/java/src/org/chromium/ui/base/ViewUtils.java',
264 ),
265 ),
Ted Chocf40ea9152023-02-14 19:02:39266 BanRule(
Ted Chocf486e3f2024-02-17 05:37:03267 'ProfileManager.getLastUsedRegularProfile()',
Ted Chocf40ea9152023-02-14 19:02:39268 (
269 'Prefer passing in the Profile reference instead of relying on the '
270 'static getLastUsedRegularProfile() call. Only top level entry points '
271 '(e.g. Activities) should call this method. Otherwise, the Profile '
272 'should either be passed in explicitly or retreived from an existing '
273 'entity with a reference to the Profile (e.g. WebContents).',
274 ),
275 False,
276 excluded_paths=(
277 r'.*Test[A-Z]?.*\.java',
278 ),
279 ),
Min Qinbc44383c2023-02-22 17:25:26280 BanRule(
281 r'/(ResourcesCompat|getResources\(\))\.getDrawable\(\)',
282 (
283 'getDrawable() can be expensive. If you have a lot of calls to '
284 'GetDrawable() or your code may introduce janks, please put your calls '
285 'inside a trace().',
286 ),
287 False,
288 excluded_paths=(
289 r'.*Test[A-Z]?.*\.java',
290 ),
291 ),
Henrique Nakashimabbf2b262023-03-10 17:21:39292 BanRule(
293 r'/RecordHistogram\.getHistogram(ValueCount|TotalCount|Samples)ForTesting\(',
294 (
295 'Raw histogram counts are easy to misuse; for example they don\'t reset '
Thiago Perrotta099034f2023-06-05 18:10:20296 'between batched tests. Use HistogramWatcher to check histogram records '
297 'instead.',
Henrique Nakashimabbf2b262023-03-10 17:21:39298 ),
299 False,
300 excluded_paths=(
301 'base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java',
302 'base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java',
303 ),
304 ),
Eric Stevensona9a980972017-09-23 00:04:41305)
306
Clement Yan9b330cb2022-11-17 05:25:29307_BANNED_JAVASCRIPT_FUNCTIONS : Sequence [BanRule] = (
308 BanRule(
309 r'/\bchrome\.send\b',
310 (
311 '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).',
312 'Please use mojo instead for new webuis. https://docs.google.com/document/d/1RF-GSUoveYa37eoyZ9EhwMtaIwoW7Z88pIgNZ9YzQi4/edit#heading=h.gkk22wgk6wff',
313 ),
314 True,
315 (
316 r'^(?!ash\/webui).+',
317 # TODO(crbug.com/1385601): pre-existing violations still need to be
318 # cleaned up.
Rebekah Potter57aa94df2022-12-13 20:30:58319 'ash/webui/common/resources/cr.m.js',
Clement Yan9b330cb2022-11-17 05:25:29320 'ash/webui/common/resources/multidevice_setup/multidevice_setup_browser_proxy.js',
Martin Bidlingmaiera921fee72023-06-03 07:52:22321 'ash/webui/common/resources/quick_unlock/lock_screen_constants.ts',
Clement Yan9b330cb2022-11-17 05:25:29322 'ash/webui/common/resources/smb_shares/smb_browser_proxy.js',
Chad Duffin06e47de2023-12-14 18:04:13323 'ash/webui/connectivity_diagnostics/resources/connectivity_diagnostics.ts',
Clement Yan9b330cb2022-11-17 05:25:29324 'ash/webui/diagnostics_ui/resources/diagnostics_browser_proxy.ts',
325 'ash/webui/multidevice_debug/resources/logs.js',
326 'ash/webui/multidevice_debug/resources/webui.js',
327 'ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js',
328 'ash/webui/projector_app/resources/app/trusted/projector_browser_proxy.js',
Ashley Prasad71f9024e2023-09-25 22:33:55329 # TODO(b/301634378): Remove violation exception once Scanning App
330 # migrated off usage of `chrome.send`.
331 'ash/webui/scanning/resources/scanning_browser_proxy.ts',
Clement Yan9b330cb2022-11-17 05:25:29332 ),
333 ),
334)
335
Daniel Cheng917ce542022-03-15 20:46:57336_BANNED_OBJC_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15337 BanRule(
[email protected]127f18ec2012-06-16 05:05:59338 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20339 (
340 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59341 'prohibited. Please use CrTrackingArea instead.',
342 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
343 ),
344 False,
345 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15346 BanRule(
[email protected]eaae1972014-04-16 04:17:26347 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20348 (
349 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59350 'instead.',
351 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
352 ),
353 False,
354 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15355 BanRule(
[email protected]127f18ec2012-06-16 05:05:59356 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20357 (
358 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59359 'Please use |convertPoint:(point) fromView:nil| instead.',
360 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
361 ),
362 True,
363 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15364 BanRule(
[email protected]127f18ec2012-06-16 05:05:59365 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20366 (
367 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59368 'Please use |convertPoint:(point) toView:nil| instead.',
369 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
370 ),
371 True,
372 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15373 BanRule(
[email protected]127f18ec2012-06-16 05:05:59374 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20375 (
376 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59377 'Please use |convertRect:(point) fromView:nil| instead.',
378 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
379 ),
380 True,
381 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15382 BanRule(
[email protected]127f18ec2012-06-16 05:05:59383 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20384 (
385 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59386 'Please use |convertRect:(point) toView:nil| instead.',
387 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
388 ),
389 True,
390 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15391 BanRule(
[email protected]127f18ec2012-06-16 05:05:59392 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20393 (
394 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59395 'Please use |convertSize:(point) fromView:nil| instead.',
396 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
397 ),
398 True,
399 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15400 BanRule(
[email protected]127f18ec2012-06-16 05:05:59401 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20402 (
403 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59404 'Please use |convertSize:(point) toView:nil| instead.',
405 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
406 ),
407 True,
408 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15409 BanRule(
jif65398702016-10-27 10:19:48410 r"/\s+UTF8String\s*]",
411 (
412 'The use of -[NSString UTF8String] is dangerous as it can return null',
413 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
414 'Please use |SysNSStringToUTF8| instead.',
415 ),
416 True,
Marijn Kruisselbrink1b7c48952023-08-31 16:58:34417 excluded_paths = (
418 '^third_party/ocmock/OCMock/',
419 ),
jif65398702016-10-27 10:19:48420 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15421 BanRule(
Sylvain Defresne4cf1d182017-09-18 14:16:34422 r'__unsafe_unretained',
423 (
424 'The use of __unsafe_unretained is almost certainly wrong, unless',
425 'when interacting with NSFastEnumeration or NSInvocation.',
426 'Please use __weak in files build with ARC, nothing otherwise.',
427 ),
428 False,
429 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15430 BanRule(
Avi Drissman7382afa02019-04-29 23:27:13431 'freeWhenDone:NO',
432 (
433 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
434 'Foundation types is prohibited.',
435 ),
436 True,
437 ),
Avi Drissman3d243a42023-08-01 16:53:59438 BanRule(
439 'This file requires ARC support.',
440 (
441 'ARC compilation is default in Chromium; do not add boilerplate to ',
442 'files that require ARC.',
443 ),
444 True,
445 ),
[email protected]127f18ec2012-06-16 05:05:59446)
447
Sylvain Defresnea8b73d252018-02-28 15:45:54448_BANNED_IOS_OBJC_FUNCTIONS = (
Daniel Chenga44a1bcd2022-03-15 20:00:15449 BanRule(
Sylvain Defresnea8b73d252018-02-28 15:45:54450 r'/\bTEST[(]',
451 (
452 'TEST() macro should not be used in Objective-C++ code as it does not ',
453 'drain the autorelease pool at the end of the test. Use TEST_F() ',
454 'macro instead with a fixture inheriting from PlatformTest (or a ',
455 'typedef).'
456 ),
457 True,
458 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15459 BanRule(
Sylvain Defresnea8b73d252018-02-28 15:45:54460 r'/\btesting::Test\b',
461 (
462 'testing::Test should not be used in Objective-C++ code as it does ',
463 'not drain the autorelease pool at the end of the test. Use ',
464 'PlatformTest instead.'
465 ),
466 True,
467 ),
Ewann2ecc8d72022-07-18 07:41:23468 BanRule(
469 ' systemImageNamed:',
470 (
471 '+[UIImage systemImageNamed:] should not be used to create symbols.',
472 'Instead use a wrapper defined in:',
Victor Vianna77a40f62023-01-31 19:04:53473 'ios/chrome/browser/ui/icons/symbol_helpers.h'
Ewann2ecc8d72022-07-18 07:41:23474 ),
475 True,
Ewann450a2ef2022-07-19 14:38:23476 excluded_paths=(
Gauthier Ambard4d8756b2023-04-07 17:26:41477 'ios/chrome/browser/shared/ui/symbols/symbol_helpers.mm',
Gauthier Ambardd36c10b12023-03-16 08:45:03478 'ios/chrome/search_widget_extension/',
Ewann450a2ef2022-07-19 14:38:23479 ),
Ewann2ecc8d72022-07-18 07:41:23480 ),
Sylvain Defresnea8b73d252018-02-28 15:45:54481)
482
Daniel Cheng917ce542022-03-15 20:46:57483_BANNED_IOS_EGTEST_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15484 BanRule(
Peter K. Lee6c03ccff2019-07-15 14:40:05485 r'/\bEXPECT_OCMOCK_VERIFY\b',
486 (
487 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
488 'it is meant for GTests. Use [mock verify] instead.'
489 ),
490 True,
491 ),
492)
493
Daniel Cheng917ce542022-03-15 20:46:57494_BANNED_CPP_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15495 BanRule(
Peter Kasting7c0d98a2023-10-06 15:42:39496 '%#0',
497 (
498 'Zero-padded values that use "#" to add prefixes don\'t exhibit ',
499 'consistent behavior, since the prefix is not prepended for zero ',
500 'values. Use "0x%0..." instead.',
501 ),
502 False,
503 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
504 ),
505 BanRule(
Peter Kasting94a56c42019-10-25 21:54:04506 r'/\busing namespace ',
507 (
508 'Using directives ("using namespace x") are banned by the Google Style',
509 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
510 'Explicitly qualify symbols or use using declarations ("using x::foo").',
511 ),
512 True,
513 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
514 ),
Antonio Gomes07300d02019-03-13 20:59:57515 # Make sure that gtest's FRIEND_TEST() macro is not used; the
516 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
517 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
Daniel Chenga44a1bcd2022-03-15 20:00:15518 BanRule(
[email protected]23e6cbc2012-06-16 18:51:20519 'FRIEND_TEST(',
520 (
[email protected]e3c945502012-06-26 20:01:49521 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20522 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
523 ),
524 False,
Arthur Sonzogni19aa4922023-08-28 17:28:59525 excluded_paths = (
526 "base/gtest_prod_util.h",
Arthur Sonzogni0bcc0232023-10-03 08:48:32527 "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/gtest_prod_util.h",
Arthur Sonzogni19aa4922023-08-28 17:28:59528 ),
[email protected]23e6cbc2012-06-16 18:51:20529 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15530 BanRule(
tomhudsone2c14d552016-05-26 17:07:46531 'setMatrixClip',
532 (
533 'Overriding setMatrixClip() is prohibited; ',
534 'the base function is deprecated. ',
535 ),
536 True,
537 (),
538 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15539 BanRule(
[email protected]52657f62013-05-20 05:30:31540 'SkRefPtr',
541 (
542 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22543 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31544 ),
545 True,
546 (),
547 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15548 BanRule(
[email protected]52657f62013-05-20 05:30:31549 'SkAutoRef',
550 (
551 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22552 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31553 ),
554 True,
555 (),
556 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15557 BanRule(
[email protected]52657f62013-05-20 05:30:31558 'SkAutoTUnref',
559 (
560 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22561 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31562 ),
563 True,
564 (),
565 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15566 BanRule(
[email protected]52657f62013-05-20 05:30:31567 'SkAutoUnref',
568 (
569 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
570 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22571 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31572 ),
573 True,
574 (),
575 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15576 BanRule(
[email protected]d89eec82013-12-03 14:10:59577 r'/HANDLE_EINTR\(.*close',
578 (
579 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
580 'descriptor will be closed, and it is incorrect to retry the close.',
581 'Either call close directly and ignore its return value, or wrap close',
582 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
583 ),
584 True,
585 (),
586 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15587 BanRule(
[email protected]d89eec82013-12-03 14:10:59588 r'/IGNORE_EINTR\((?!.*close)',
589 (
590 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
591 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
592 ),
593 True,
594 (
595 # Files that #define IGNORE_EINTR.
Bruce Dawson40fece62022-09-16 19:58:31596 r'^base/posix/eintr_wrapper\.h$',
597 r'^ppapi/tests/test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59598 ),
599 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15600 BanRule(
[email protected]ec5b3f02014-04-04 18:43:43601 r'/v8::Extension\(',
602 (
603 'Do not introduce new v8::Extensions into the code base, use',
604 'gin::Wrappable instead. See http://crbug.com/334679',
605 ),
606 True,
[email protected]f55c90ee62014-04-12 00:50:03607 (
Bruce Dawson40fece62022-09-16 19:58:31608 r'extensions/renderer/safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03609 ),
[email protected]ec5b3f02014-04-04 18:43:43610 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15611 BanRule(
jame2d1a952016-04-02 00:27:10612 '#pragma comment(lib,',
613 (
614 'Specify libraries to link with in build files and not in the source.',
615 ),
616 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41617 (
Bruce Dawson40fece62022-09-16 19:58:31618 r'^base/third_party/symbolize/.*',
619 r'^third_party/abseil-cpp/.*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41620 ),
jame2d1a952016-04-02 00:27:10621 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15622 BanRule(
Gabriel Charette7cc6c432018-04-25 20:52:02623 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59624 (
625 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
626 ),
627 False,
628 (),
629 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15630 BanRule(
Gabriel Charette7cc6c432018-04-25 20:52:02631 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59632 (
633 'Consider using THREAD_CHECKER macros instead of the class directly.',
634 ),
635 False,
636 (),
637 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15638 BanRule(
Sean Maher03efef12022-09-23 22:43:13639 r'/\b(?!(Sequenced|SingleThread))\w*TaskRunner::(GetCurrentDefault|CurrentDefaultHandle)',
640 (
641 'It is not allowed to call these methods from the subclasses ',
642 'of Sequenced or SingleThread task runners.',
643 ),
644 True,
645 (),
646 ),
647 BanRule(
Yuri Wiitala2f8de5c2017-07-21 00:11:06648 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
649 (
650 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
651 'deprecated (http://crbug.com/634507). Please avoid converting away',
652 'from the Time types in Chromium code, especially if any math is',
653 'being done on time values. For interfacing with platform/library',
Peter Kasting8a2605652023-09-14 03:57:15654 'APIs, use base::Time::(From,To)DeltaSinceWindowsEpoch() or',
655 'base::{TimeDelta::In}Microseconds(), or one of the other type',
656 'converter methods instead. For faking TimeXXX values (for unit',
Peter Kasting53fd6ee2021-10-05 20:40:48657 'testing only), use TimeXXX() + Microseconds(N). For',
Yuri Wiitala2f8de5c2017-07-21 00:11:06658 'other use cases, please contact base/time/OWNERS.',
659 ),
660 False,
Arthur Sonzogni19aa4922023-08-28 17:28:59661 excluded_paths = (
662 "base/time/time.h",
Arthur Sonzogni0bcc0232023-10-03 08:48:32663 "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h",
Arthur Sonzogni19aa4922023-08-28 17:28:59664 ),
Yuri Wiitala2f8de5c2017-07-21 00:11:06665 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15666 BanRule(
dbeamb6f4fde2017-06-15 04:03:06667 'CallJavascriptFunctionUnsafe',
668 (
669 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
670 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
671 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
672 ),
673 False,
674 (
Bruce Dawson40fece62022-09-16 19:58:31675 r'^content/browser/webui/web_ui_impl\.(cc|h)$',
676 r'^content/public/browser/web_ui\.h$',
677 r'^content/public/test/test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06678 ),
679 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15680 BanRule(
dskiba1474c2bfd62017-07-20 02:19:24681 'leveldb::DB::Open',
682 (
683 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
684 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
685 "Chrome's tracing, making their memory usage visible.",
686 ),
687 True,
688 (
689 r'^third_party/leveldatabase/.*\.(cc|h)$',
690 ),
Gabriel Charette0592c3a2017-07-26 12:02:04691 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15692 BanRule(
Chris Mumfordc38afb62017-10-09 17:55:08693 'leveldb::NewMemEnv',
694 (
695 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58696 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
697 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08698 ),
699 True,
700 (
701 r'^third_party/leveldatabase/.*\.(cc|h)$',
702 ),
703 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15704 BanRule(
Gabriel Charetted9839bc2017-07-29 14:17:47705 'RunLoop::QuitCurrent',
706 (
Robert Liao64b7ab22017-08-04 23:03:43707 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
708 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47709 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41710 False,
Gabriel Charetted9839bc2017-07-29 14:17:47711 (),
Gabriel Charettea44975052017-08-21 23:14:04712 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15713 BanRule(
Gabriel Charettea44975052017-08-21 23:14:04714 'base::ScopedMockTimeMessageLoopTaskRunner',
715 (
Gabriel Charette87cc1af2018-04-25 20:52:51716 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11717 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51718 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
719 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
720 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04721 ),
Gabriel Charette87cc1af2018-04-25 20:52:51722 False,
Gabriel Charettea44975052017-08-21 23:14:04723 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57724 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15725 BanRule(
Dave Tapuska98199b612019-07-10 13:30:44726 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57727 (
728 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02729 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57730 ),
731 True,
Robert Ogden4c43a712023-06-28 22:03:19732 [
733 # Abseil's benchmarks never linked into chrome.
734 'third_party/abseil-cpp/.*_benchmark.cc',
Robert Ogden4c43a712023-06-28 22:03:19735 ],
Francois Doray43670e32017-09-27 12:40:38736 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15737 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:08738 r'/\bstd::sto(i|l|ul|ll|ull)\b',
Peter Kasting991618a62019-06-17 22:00:09739 (
Peter Kastinge2c5ee82023-02-15 17:23:08740 'std::sto{i,l,ul,ll,ull}() use exceptions to communicate results. ',
741 'Use base::StringTo[U]Int[64]() instead.',
Peter Kasting991618a62019-06-17 22:00:09742 ),
743 True,
744 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
745 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15746 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:08747 r'/\bstd::sto(f|d|ld)\b',
Peter Kasting991618a62019-06-17 22:00:09748 (
Peter Kastinge2c5ee82023-02-15 17:23:08749 'std::sto{f,d,ld}() use exceptions to communicate results. ',
Peter Kasting991618a62019-06-17 22:00:09750 'For locale-independent values, e.g. reading numbers from disk',
751 'profiles, use base::StringToDouble().',
752 'For user-visible values, parse using ICU.',
753 ),
754 True,
755 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
756 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15757 BanRule(
Daniel Bratell69334cc2019-03-26 11:07:45758 r'/\bstd::to_string\b',
759 (
Peter Kastinge2c5ee82023-02-15 17:23:08760 'std::to_string() is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09761 'For locale-independent strings, e.g. writing numbers to disk',
762 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45763 'For user-visible strings, use base::FormatNumber() and',
764 'the related functions in base/i18n/number_formatting.h.',
765 ),
Daniel Cheng3498f422024-04-19 17:36:19766 True,
767 [
768 # TODO(crbug.com/335672557): Please do not add to this list. Existing
769 # uses should removed.
Daniel Cheng3498f422024-04-19 17:36:19770 "base/linux_util.cc",
Daniel Cheng3498f422024-04-19 17:36:19771 "chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc",
772 "chrome/test/chromedriver/chrome/web_view_impl.cc",
773 "chrome/test/chromedriver/log_replay/log_replay_socket.cc",
774 "chromecast/crash/linux/dump_info.cc",
775 "chromeos/ash/components/dbus/biod/fake_biod_client.cc",
776 "chromeos/ash/components/dbus/biod/fake_biod_client_unittest.cc",
777 "chromeos/ash/components/report/utils/time_utils.cc",
778 "chromeos/ash/services/device_sync/cryptauth_device_manager_impl.cc",
779 "chromeos/ash/services/device_sync/cryptauth_device_manager_impl_unittest.cc",
780 "chromeos/ash/services/secure_channel/ble_weave_packet_receiver.cc",
781 "chromeos/ash/services/secure_channel/bluetooth_helper_impl_unittest.cc",
782 "chromeos/process_proxy/process_proxy.cc",
783 "components/chromeos_camera/jpeg_encode_accelerator_unittest.cc",
784 "components/cronet/native/perftest/perf_test.cc",
785 "components/download/internal/common/download_item_impl_unittest.cc",
786 "components/gcm_driver/gcm_client_impl_unittest.cc",
787 "components/history/core/test/fake_web_history_service.cc",
788 "components/history_clusters/core/clustering_test_utils.cc",
789 "components/language/content/browser/ulp_language_code_locator/s2langquadtree_datatest.cc",
790 "components/live_caption/views/caption_bubble_controller_views.cc",
791 "components/offline_pages/core/offline_event_logger_unittest.cc",
792 "components/offline_pages/core/offline_page_model_event_logger.cc",
793 "components/omnibox/browser/history_quick_provider_performance_unittest.cc",
794 "components/omnibox/browser/in_memory_url_index_unittest.cc",
795 "components/payments/content/payment_method_manifest_table_unittest.cc",
796 "components/policy/core/common/cloud/device_management_service_unittest.cc",
797 "components/policy/core/common/schema.cc",
798 "components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc",
799 "components/tracing/test/trace_event_perftest.cc",
800 "components/ui_devtools/views/overlay_agent_views.cc",
801 "components/url_pattern_index/closed_hash_map_unittest.cc",
802 "components/url_pattern_index/url_pattern_index_unittest.cc",
803 "content/browser/accessibility/accessibility_tree_formatter_blink.cc",
804 "content/browser/background_fetch/mock_background_fetch_delegate.cc",
805 "content/browser/background_fetch/storage/database_helpers.cc",
806 "content/browser/background_sync/background_sync_launcher_unittest.cc",
807 "content/browser/browser_child_process_host_impl.cc",
808 "content/browser/devtools/protocol/security_handler.cc",
809 "content/browser/notifications/platform_notification_context_trigger_unittest.cc",
810 "content/browser/renderer_host/input/touch_action_browsertest.cc",
811 "content/browser/renderer_host/render_process_host_impl.cc",
812 "content/browser/renderer_host/text_input_manager.cc",
813 "content/browser/sandbox_parameters_mac.mm",
814 "device/fido/mock_fido_device.cc",
Daniel Cheng3498f422024-04-19 17:36:19815 "gpu/command_buffer/tests/gl_webgl_multi_draw_test.cc",
816 "gpu/config/gpu_control_list.cc",
817 "media/audio/win/core_audio_util_win.cc",
818 "media/gpu/android/media_codec_video_decoder.cc",
819 "media/gpu/vaapi/vaapi_wrapper.cc",
820 "remoting/host/linux/certificate_watcher_unittest.cc",
821 "testing/libfuzzer/fuzzers/url_parse_proto_fuzzer.cc",
822 "testing/libfuzzer/proto/url_proto_converter.cc",
823 "third_party/blink/renderer/core/css/parser/css_proto_converter.cc",
824 "third_party/blink/renderer/core/editing/ime/edit_context.cc",
825 "third_party/blink/renderer/platform/graphics/bitmap_image_test.cc",
826 "tools/binary_size/libsupersize/viewer/caspian/diff_test.cc",
827 "tools/binary_size/libsupersize/viewer/caspian/tree_builder_test.cc",
828 "ui/base/ime/win/tsf_text_store.cc",
829 "ui/ozone/platform/drm/gpu/hardware_display_plane.cc",
830 _THIRD_PARTY_EXCEPT_BLINK],
Daniel Bratell69334cc2019-03-26 11:07:45831 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15832 BanRule(
Peter Kasting6f79b202023-08-09 21:25:41833 r'/#include <(cctype|ctype\.h|cwctype|wctype.h)>',
834 (
835 '<cctype>/<ctype.h>/<cwctype>/<wctype.h> are banned. Use',
836 '"third_party/abseil-cpp/absl/strings/ascii.h" instead.',
837 ),
838 True,
839 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
840 ),
841 BanRule(
Daniel Bratell69334cc2019-03-26 11:07:45842 r'/\bstd::shared_ptr\b',
843 (
Peter Kastinge2c5ee82023-02-15 17:23:08844 'std::shared_ptr is banned. Use scoped_refptr instead.',
Daniel Bratell69334cc2019-03-26 11:07:45845 ),
846 True,
Ulan Degenbaev947043882021-02-10 14:02:31847 [
848 # Needed for interop with third-party library.
849 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
Alex Chau9eb03cdd52020-07-13 21:04:57850 'array_buffer_contents\.(cc|h)',
Ben Kelly39bf6bef2021-10-04 22:54:58851 '^third_party/blink/renderer/bindings/core/v8/' +
852 'v8_wasm_response_extensions.cc',
Wez5f56be52021-05-04 09:30:58853 '^gin/array_buffer\.(cc|h)',
Jiahe Zhange97ba772023-07-27 02:46:41854 '^gin/per_isolate_data\.(cc|h)',
Wez5f56be52021-05-04 09:30:58855 '^chrome/services/sharing/nearby/',
Stephen Nuskoe09c8ef22022-09-29 00:47:28856 # Needed for interop with third-party library libunwindstack.
Stephen Nuskoe51c1382022-09-26 15:49:03857 '^base/profiler/libunwindstack_unwinder_android\.(cc|h)',
Thiabaud Engelbrecht42e09812023-08-29 21:19:30858 '^base/profiler/native_unwinder_android_memory_regions_map_impl.(cc|h)',
Bob Beck03509d282022-12-07 21:49:05859 # Needed for interop with third-party boringssl cert verifier
860 '^third_party/boringssl/',
861 '^net/cert/',
862 '^net/tools/cert_verify_tool/',
863 '^services/cert_verifier/',
864 '^components/certificate_transparency/',
865 '^components/media_router/common/providers/cast/certificate/',
Meilin Wang00efc7c2021-05-13 01:12:42866 # gRPC provides some C++ libraries that use std::shared_ptr<>.
Yeunjoo Choi1b644402022-08-25 02:36:10867 '^chromeos/ash/services/libassistant/grpc/',
Vigen Issahhanjanfdf9de52021-12-22 21:13:59868 '^chromecast/cast_core/grpc',
869 '^chromecast/cast_core/runtime/browser',
Yue Shef83d95202022-09-26 20:23:45870 '^ios/chrome/test/earl_grey/chrome_egtest_plugin_client\.(mm|h)',
Wez5f56be52021-05-04 09:30:58871 # Fuchsia provides C++ libraries that use std::shared_ptr<>.
Wez6da2e412022-11-23 11:28:48872 '^base/fuchsia/.*\.(cc|h)',
Wez5f56be52021-05-04 09:30:58873 '.*fuchsia.*test\.(cc|h)',
miktb599ed12023-05-26 07:03:56874 # Clang plugins have different build config.
875 '^tools/clang/plugins/',
Alex Chau9eb03cdd52020-07-13 21:04:57876 _THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell609102be2019-03-27 20:53:21877 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15878 BanRule(
Peter Kasting991618a62019-06-17 22:00:09879 r'/\bstd::weak_ptr\b',
880 (
Peter Kastinge2c5ee82023-02-15 17:23:08881 'std::weak_ptr is banned. Use base::WeakPtr instead.',
Peter Kasting991618a62019-06-17 22:00:09882 ),
883 True,
884 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
885 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15886 BanRule(
Daniel Bratell609102be2019-03-27 20:53:21887 r'/\blong long\b',
888 (
Peter Kastinge2c5ee82023-02-15 17:23:08889 'long long is banned. Use [u]int64_t instead.',
Daniel Bratell609102be2019-03-27 20:53:21890 ),
891 False, # Only a warning since it is already used.
892 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
893 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15894 BanRule(
Daniel Cheng192683f2022-11-01 20:52:44895 r'/\b(absl|std)::any\b',
Daniel Chengc05fcc62022-01-12 16:54:29896 (
Peter Kastinge2c5ee82023-02-15 17:23:08897 '{absl,std}::any are banned due to incompatibility with the component ',
898 'build.',
Daniel Chengc05fcc62022-01-12 16:54:29899 ),
900 True,
901 # Not an error in third party folders, though it probably should be :)
902 [_THIRD_PARTY_EXCEPT_BLINK],
903 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15904 BanRule(
Daniel Bratell609102be2019-03-27 20:53:21905 r'/\bstd::bind\b',
906 (
Peter Kastinge2c5ee82023-02-15 17:23:08907 'std::bind() is banned because of lifetime risks. Use ',
908 'base::Bind{Once,Repeating}() instead.',
Daniel Bratell609102be2019-03-27 20:53:21909 ),
910 True,
911 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
912 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15913 BanRule(
Daniel Cheng192683f2022-11-01 20:52:44914 (
Peter Kastingc7460d982023-03-14 21:01:42915 r'/\bstd::(?:'
916 r'linear_congruential_engine|mersenne_twister_engine|'
917 r'subtract_with_carry_engine|discard_block_engine|'
918 r'independent_bits_engine|shuffle_order_engine|'
919 r'minstd_rand0?|mt19937(_64)?|ranlux(24|48)(_base)?|knuth_b|'
920 r'default_random_engine|'
921 r'random_device|'
922 r'seed_seq'
Daniel Cheng192683f2022-11-01 20:52:44923 r')\b'
924 ),
925 (
926 'STL random number engines and generators are banned. Use the ',
927 'helpers in base/rand_util.h instead, e.g. base::RandBytes() or ',
928 'base::RandomBitGenerator.'
Daniel Cheng57d967762023-10-10 19:03:06929 '',
930 'Please reach out to [email protected] if the base APIs are ',
931 'insufficient for your needs.',
Daniel Cheng192683f2022-11-01 20:52:44932 ),
933 True,
934 [
935 # Not an error in third_party folders.
936 _THIRD_PARTY_EXCEPT_BLINK,
937 # Various tools which build outside of Chrome.
938 r'testing/libfuzzer',
939 r'tools/android/io_benchmark/',
940 # Fuzzers are allowed to use standard library random number generators
941 # since fuzzing speed + reproducibility is important.
942 r'tools/ipc_fuzzer/',
943 r'.+_fuzzer\.cc$',
944 r'.+_fuzzertest\.cc$',
945 # TODO(https://crbug.com/1380528): These are all unsanctioned uses of
946 # the standard library's random number generators, and should be
947 # migrated to the //base equivalent.
948 r'ash/ambient/model/ambient_topic_queue\.cc',
Arthur Sonzogni0bcc0232023-10-03 08:48:32949 r'base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest\.cc',
Daniel Cheng192683f2022-11-01 20:52:44950 r'base/ranges/algorithm_unittest\.cc',
951 r'base/test/launcher/test_launcher\.cc',
952 r'cc/metrics/video_playback_roughness_reporter_unittest\.cc',
953 r'chrome/browser/apps/app_service/metrics/website_metrics\.cc',
954 r'chrome/browser/ash/power/auto_screen_brightness/monotone_cubic_spline_unittest\.cc',
955 r'chrome/browser/ash/printing/zeroconf_printer_detector_unittest\.cc',
956 r'chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl_unittest\.cc',
957 r'chrome/browser/nearby_sharing/contacts/nearby_share_contacts_sorter_unittest\.cc',
958 r'chrome/browser/privacy_budget/mesa_distribution_unittest\.cc',
959 r'chrome/browser/web_applications/test/web_app_test_utils\.cc',
960 r'chrome/browser/web_applications/test/web_app_test_utils\.cc',
961 r'chrome/browser/win/conflicts/module_blocklist_cache_util_unittest\.cc',
Daniel Cheng192683f2022-11-01 20:52:44962 r'chromeos/ash/components/memory/userspace_swap/swap_storage_unittest\.cc',
963 r'chromeos/ash/components/memory/userspace_swap/userspace_swap\.cc',
964 r'components/metrics/metrics_state_manager\.cc',
965 r'components/omnibox/browser/history_quick_provider_performance_unittest\.cc',
966 r'components/zucchini/disassembler_elf_unittest\.cc',
967 r'content/browser/webid/federated_auth_request_impl\.cc',
968 r'content/browser/webid/federated_auth_request_impl\.cc',
969 r'media/cast/test/utility/udp_proxy\.h',
970 r'sql/recover_module/module_unittest\.cc',
Samarc64873a72023-10-10 09:19:12971 r'components/search_engines/template_url_prepopulate_data.cc',
Daniel Cheng57d967762023-10-10 19:03:06972 # Do not add new entries to this list. If you have a use case which is
973 # not satisfied by the current APIs (i.e. you need an explicitly-seeded
974 # sequence, or stability of some sort is required), please contact
975 # [email protected].
Daniel Cheng192683f2022-11-01 20:52:44976 ],
977 ),
978 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:08979 r'/\b(absl,std)::bind_front\b',
Peter Kasting4f35bfc2022-10-18 18:39:12980 (
Peter Kastinge2c5ee82023-02-15 17:23:08981 '{absl,std}::bind_front() are banned. Use base::Bind{Once,Repeating}() '
982 'instead.',
Peter Kasting4f35bfc2022-10-18 18:39:12983 ),
984 True,
985 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
986 ),
987 BanRule(
988 r'/\bABSL_FLAG\b',
989 (
990 'ABSL_FLAG is banned. Use base::CommandLine instead.',
991 ),
992 True,
993 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
994 ),
995 BanRule(
996 r'/\babsl::c_',
997 (
Peter Kastinge2c5ee82023-02-15 17:23:08998 'Abseil container utilities are banned. Use base/ranges/algorithm.h ',
Peter Kasting4f35bfc2022-10-18 18:39:12999 'instead.',
1000 ),
1001 True,
1002 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1003 ),
1004 BanRule(
Peter Kasting431239a2023-09-29 03:11:441005 r'/\babsl::FixedArray\b',
1006 (
1007 'absl::FixedArray is banned. Use base::FixedArray instead.',
1008 ),
1009 True,
1010 [
1011 # base::FixedArray provides canonical access.
1012 r'^base/types/fixed_array.h',
1013 # Not an error in third_party folders.
1014 _THIRD_PARTY_EXCEPT_BLINK,
1015 ],
1016 ),
1017 BanRule(
Peter Kasting4f35bfc2022-10-18 18:39:121018 r'/\babsl::FunctionRef\b',
1019 (
1020 'absl::FunctionRef is banned. Use base::FunctionRef instead.',
1021 ),
1022 True,
1023 [
1024 # base::Bind{Once,Repeating} references absl::FunctionRef to disallow
1025 # interoperability.
1026 r'^base/functional/bind_internal\.h',
1027 # base::FunctionRef is implemented on top of absl::FunctionRef.
1028 r'^base/functional/function_ref.*\..+',
1029 # Not an error in third_party folders.
1030 _THIRD_PARTY_EXCEPT_BLINK,
1031 ],
1032 ),
1033 BanRule(
1034 r'/\babsl::(Insecure)?BitGen\b',
1035 (
Daniel Cheng192683f2022-11-01 20:52:441036 'absl random number generators are banned. Use the helpers in '
1037 'base/rand_util.h instead, e.g. base::RandBytes() or ',
1038 'base::RandomBitGenerator.'
Peter Kasting4f35bfc2022-10-18 18:39:121039 ),
1040 True,
1041 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1042 ),
1043 BanRule(
danakj44190ab62024-02-08 01:55:491044 r'/(\babsl::Span\b|#include <span>|\bstd::span\b)',
Peter Kasting4f35bfc2022-10-18 18:39:121045 (
danakj44190ab62024-02-08 01:55:491046 'absl::Span and std::span are not allowed ',
Peter Kastinge2c5ee82023-02-15 17:23:081047 '(https://crbug.com/1414652). Use base::span instead.',
Peter Kasting4f35bfc2022-10-18 18:39:121048 ),
1049 True,
Victor Vasiliev23b9ea6a2023-01-05 19:42:291050 [
danakj44190ab62024-02-08 01:55:491051 # Included for conversions between base and std.
1052 r'base/containers/span.h',
Tom Sepez3b060e32024-01-25 00:14:321053 # Test base::span<> compatibility against std::span<>.
1054 r'base/containers/span_unittest.cc',
Victor Vasiliev23b9ea6a2023-01-05 19:42:291055 # Needed to use QUICHE API.
Tsuyoshi Horo758bdb02024-03-14 08:47:241056 r'net/third_party/quiche/overrides/quiche_platform_impl/quiche_stack_trace_impl\.*',
Victor Vasiliev23b9ea6a2023-01-05 19:42:291057 r'services/network/web_transport\.cc',
Brianna Goldstein846d8002023-05-16 19:24:301058 r'chrome/browser/ip_protection/.*',
Ciara McMullinacdb1122024-04-30 18:20:331059 r'components/ip_protection/.*',
Victor Vasiliev23b9ea6a2023-01-05 19:42:291060 # Not an error in third_party folders.
danakj590d15232024-02-08 17:17:441061 _THIRD_PARTY_EXCEPT_BLINK,
1062 # //base/numerics can't use base or absl.
1063 r'base/numerics/.*'
Victor Vasiliev23b9ea6a2023-01-05 19:42:291064 ],
Peter Kasting4f35bfc2022-10-18 18:39:121065 ),
1066 BanRule(
1067 r'/\babsl::StatusOr\b',
1068 (
1069 'absl::StatusOr is banned. Use base::expected instead.',
1070 ),
1071 True,
Adithya Srinivasanb2041882022-10-21 19:34:201072 [
1073 # Needed to use liburlpattern API.
Tsuyoshi Horoa150b902024-02-05 01:27:151074 r'components/url_pattern/.*',
1075 r'services/network/shared_dictionary/simple_url_pattern_matcher\.cc',
Adithya Srinivasanb2041882022-10-21 19:34:201076 r'third_party/blink/renderer/core/url_pattern/.*',
Louise Brettc6d23872023-04-11 02:48:321077 r'third_party/blink/renderer/modules/manifest/manifest_parser\.cc',
Brianna Goldstein846d8002023-05-16 19:24:301078 # Needed to use QUICHE API.
1079 r'chrome/browser/ip_protection/.*',
Ciara McMullinacdb1122024-04-30 18:20:331080 r'components/ip_protection/.*',
Piotr Bialecki7f2549fd2023-10-17 17:49:461081 # Needed to use MediaPipe API.
1082 r'components/media_effects/.*\.cc',
Adithya Srinivasanb2041882022-10-21 19:34:201083 # Not an error in third_party folders.
1084 _THIRD_PARTY_EXCEPT_BLINK
1085 ],
Peter Kasting4f35bfc2022-10-18 18:39:121086 ),
1087 BanRule(
1088 r'/\babsl::StrFormat\b',
1089 (
Peter Kastinge2c5ee82023-02-15 17:23:081090 'absl::StrFormat() is not allowed yet (https://crbug.com/1371963). ',
1091 'Use base::StringPrintf() instead.',
Peter Kasting4f35bfc2022-10-18 18:39:121092 ),
1093 True,
1094 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1095 ),
1096 BanRule(
Peter Kasting4f35bfc2022-10-18 18:39:121097 r'/\babsl::(StrSplit|StrJoin|StrCat|StrAppend|Substitute|StrContains)\b',
1098 (
1099 'Abseil string utilities are banned. Use base/strings instead.',
1100 ),
1101 True,
1102 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1103 ),
1104 BanRule(
1105 r'/\babsl::(Mutex|CondVar|Notification|Barrier|BlockingCounter)\b',
1106 (
1107 'Abseil synchronization primitives are banned. Use',
1108 'base/synchronization instead.',
1109 ),
1110 True,
1111 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1112 ),
1113 BanRule(
1114 r'/\babsl::(Duration|Time|TimeZone|CivilDay)\b',
1115 (
1116 'Abseil\'s time library is banned. Use base/time instead.',
1117 ),
1118 True,
Dustin J. Mitchell626a6d322023-06-26 15:02:481119 [
1120 # Needed to use QUICHE API.
1121 r'chrome/browser/ip_protection/.*',
Ciara McMullinacdb1122024-04-30 18:20:331122 r'components/ip_protection/.*',
Victor Vasilieva8638882023-09-25 16:41:041123 r'services/network/web_transport.*',
Juliet Levesqueda2044412024-04-18 21:17:171124 # Needed to integrate with //third_party/nearby
1125 r'components/cross_device/nearby/system_clock.cc',
Dustin J. Mitchell626a6d322023-06-26 15:02:481126 _THIRD_PARTY_EXCEPT_BLINK # Not an error in third_party folders.
1127 ],
Peter Kasting4f35bfc2022-10-18 18:39:121128 ),
1129 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081130 r'/#include <chrono>',
Daniel Bratell609102be2019-03-27 20:53:211131 (
Peter Kastinge2c5ee82023-02-15 17:23:081132 '<chrono> is banned. Use base/time instead.',
Daniel Bratell609102be2019-03-27 20:53:211133 ),
1134 True,
Arthur Sonzogni2ee5e382023-09-11 09:13:031135 [
1136 # Not an error in third_party folders:
1137 _THIRD_PARTY_EXCEPT_BLINK,
1138 # PartitionAlloc's starscan, doesn't depend on base/. It can't use
1139 # base::ConditionalVariable::TimedWait(..).
Arthur Sonzogni0bcc0232023-10-03 08:48:321140 "base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.cc",
Takuto Ikutad0bcf2122024-04-17 15:37:041141 # This uses openscreen API depending on std::chrono.
1142 "components/openscreen_platform/task_runner.cc",
Arthur Sonzogni2ee5e382023-09-11 09:13:031143 ]
Daniel Bratell609102be2019-03-27 20:53:211144 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151145 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081146 r'/#include <exception>',
Daniel Bratell609102be2019-03-27 20:53:211147 (
1148 'Exceptions are banned and disabled in Chromium.',
1149 ),
1150 True,
1151 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1152 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151153 BanRule(
Daniel Bratell609102be2019-03-27 20:53:211154 r'/\bstd::function\b',
1155 (
Peter Kastinge2c5ee82023-02-15 17:23:081156 'std::function is banned. Use base::{Once,Repeating}Callback instead.',
Daniel Bratell609102be2019-03-27 20:53:211157 ),
Daniel Chenge5583e3c2022-09-22 00:19:411158 True,
Daniel Chengcd23b8b2022-09-16 17:16:241159 [
1160 # Has tests that template trait helpers don't unintentionally match
1161 # std::function.
Daniel Chenge5583e3c2022-09-22 00:19:411162 r'base/functional/callback_helpers_unittest\.cc',
1163 # Required to implement interfaces from the third-party perfetto
1164 # library.
1165 r'base/tracing/perfetto_task_runner\.cc',
1166 r'base/tracing/perfetto_task_runner\.h',
1167 # Needed for interop with the third-party nearby library type
1168 # location::nearby::connections::ResultCallback.
1169 'chrome/services/sharing/nearby/nearby_connections_conversions\.cc'
1170 # Needed for interop with the internal libassistant library.
1171 'chromeos/ash/services/libassistant/callback_utils\.h',
1172 # Needed for interop with Fuchsia fidl APIs.
1173 'fuchsia_web/webengine/browser/context_impl_browsertest\.cc',
1174 'fuchsia_web/webengine/browser/cookie_manager_impl_unittest\.cc',
1175 'fuchsia_web/webengine/browser/media_player_impl_unittest\.cc',
Ken Rockot2af0d1742023-11-22 17:03:471176 # Required to interop with interfaces from the third-party ChromeML
1177 # library API.
1178 'services/on_device_model/ml/chrome_ml_api\.h',
1179 'services/on_device_model/ml/on_device_model_executor\.cc',
1180 'services/on_device_model/ml/on_device_model_executor\.h',
Daniel Chenge5583e3c2022-09-22 00:19:411181 # Required to interop with interfaces from the third-party perfetto
1182 # library.
1183 'services/tracing/public/cpp/perfetto/custom_event_recorder\.cc',
1184 'services/tracing/public/cpp/perfetto/perfetto_traced_process\.cc',
1185 'services/tracing/public/cpp/perfetto/perfetto_traced_process\.h',
1186 'services/tracing/public/cpp/perfetto/perfetto_tracing_backend\.cc',
1187 'services/tracing/public/cpp/perfetto/producer_client\.cc',
1188 'services/tracing/public/cpp/perfetto/producer_client\.h',
1189 'services/tracing/public/cpp/perfetto/producer_test_utils\.cc',
1190 'services/tracing/public/cpp/perfetto/producer_test_utils\.h',
1191 # Required for interop with the third-party webrtc library.
1192 'third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl\.cc',
1193 'third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl\.h',
Daniel Chenge5583e3c2022-09-22 00:19:411194 # TODO(https://crbug.com/1364577): Various uses that should be
1195 # migrated to something else.
1196 # Should use base::OnceCallback or base::RepeatingCallback.
1197 'base/allocator/dispatcher/initializer_unittest\.cc',
1198 'chrome/browser/ash/accessibility/speech_monitor\.cc',
1199 'chrome/browser/ash/accessibility/speech_monitor\.h',
1200 'chrome/browser/ash/login/ash_hud_login_browsertest\.cc',
1201 'chromecast/base/observer_unittest\.cc',
1202 'chromecast/browser/cast_web_view\.h',
1203 'chromecast/public/cast_media_shlib\.h',
1204 'device/bluetooth/floss/exported_callback_manager\.h',
1205 'device/bluetooth/floss/floss_dbus_client\.h',
1206 'device/fido/cable/v2_handshake_unittest\.cc',
1207 'device/fido/pin\.cc',
1208 'services/tracing/perfetto/test_utils\.h',
1209 # Should use base::FunctionRef.
1210 'chrome/browser/media/webrtc/test_stats_dictionary\.cc',
1211 'chrome/browser/media/webrtc/test_stats_dictionary\.h',
1212 'chromeos/ash/services/libassistant/device_settings_controller\.cc',
1213 'components/browser_ui/client_certificate/android/ssl_client_certificate_request\.cc',
1214 'components/gwp_asan/client/sampling_malloc_shims_unittest\.cc',
1215 'content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest\.cc',
1216 # Does not need std::function at all.
1217 'components/omnibox/browser/autocomplete_result\.cc',
1218 'device/fido/win/webauthn_api\.cc',
1219 'media/audio/alsa/alsa_util\.cc',
1220 'media/remoting/stream_provider\.h',
1221 'sql/vfs_wrapper\.cc',
1222 # TODO(https://crbug.com/1364585): Remove usage and exception list
1223 # entries.
1224 'extensions/renderer/api/automation/automation_internal_custom_bindings\.cc',
1225 'extensions/renderer/api/automation/automation_internal_custom_bindings\.h',
1226 # TODO(https://crbug.com/1364579): Remove usage and exception list
1227 # entry.
1228 'ui/views/controls/focus_ring\.h',
1229
1230 # Various pre-existing uses in //tools that is low-priority to fix.
1231 'tools/binary_size/libsupersize/viewer/caspian/diff\.cc',
1232 'tools/binary_size/libsupersize/viewer/caspian/model\.cc',
1233 'tools/binary_size/libsupersize/viewer/caspian/model\.h',
1234 'tools/binary_size/libsupersize/viewer/caspian/tree_builder\.h',
1235 'tools/clang/base_bind_rewriters/BaseBindRewriters\.cpp',
1236
Daniel Chengcd23b8b2022-09-16 17:16:241237 # Not an error in third_party folders.
1238 _THIRD_PARTY_EXCEPT_BLINK
1239 ],
Daniel Bratell609102be2019-03-27 20:53:211240 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151241 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081242 r'/#include <X11/',
Tom Andersona95e12042020-09-09 23:08:001243 (
1244 'Do not use Xlib. Use xproto (from //ui/gfx/x:xproto) instead.',
1245 ),
1246 True,
1247 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1248 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151249 BanRule(
Daniel Bratell609102be2019-03-27 20:53:211250 r'/\bstd::ratio\b',
1251 (
1252 'std::ratio is banned by the Google Style Guide.',
1253 ),
1254 True,
1255 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:451256 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151257 BanRule(
Peter Kasting6d77e9d2023-02-09 21:58:181258 r'/\bstd::aligned_alloc\b',
1259 (
Peter Kastinge2c5ee82023-02-15 17:23:081260 'std::aligned_alloc() is not yet allowed (crbug.com/1412818). Use ',
1261 'base::AlignedAlloc() instead.',
Peter Kasting6d77e9d2023-02-09 21:58:181262 ),
1263 True,
1264 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1265 ),
1266 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081267 r'/#include <(barrier|latch|semaphore|stop_token)>',
Peter Kasting6d77e9d2023-02-09 21:58:181268 (
Peter Kastinge2c5ee82023-02-15 17:23:081269 'The thread support library is banned. Use base/synchronization '
1270 'instead.',
Peter Kasting6d77e9d2023-02-09 21:58:181271 ),
1272 True,
1273 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1274 ),
1275 BanRule(
Helmut Januschka7cc8a84f2024-02-07 22:50:411276 r'/\bstd::execution::(par|seq)\b',
1277 (
1278 'std::execution::(par|seq) is banned; they do not fit into '
1279 ' Chrome\'s threading model, and libc++ doesn\'t have full '
1280 'support.'
1281 ),
1282 True,
1283 [_THIRD_PARTY_EXCEPT_BLINK],
1284 ),
1285 BanRule(
Avi Drissman70cb7f72023-12-12 17:44:371286 r'/\bstd::bit_cast\b',
1287 (
1288 'std::bit_cast is banned; use base::bit_cast instead for values and '
1289 'standard C++ casting when pointers are involved.',
1290 ),
1291 True,
danakj590d15232024-02-08 17:17:441292 [
1293 # Don't warn in third_party folders.
1294 _THIRD_PARTY_EXCEPT_BLINK,
1295 # //base/numerics can't use base or absl.
1296 r'base/numerics/.*'
1297 ],
Avi Drissman70cb7f72023-12-12 17:44:371298 ),
1299 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081300 r'/\bstd::(c8rtomb|mbrtoc8)\b',
Peter Kasting6d77e9d2023-02-09 21:58:181301 (
Peter Kastinge2c5ee82023-02-15 17:23:081302 'std::c8rtomb() and std::mbrtoc8() are banned.',
Peter Kasting6d77e9d2023-02-09 21:58:181303 ),
1304 True,
1305 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1306 ),
1307 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081308 r'/\bchar8_t|std::u8string\b',
Peter Kasting6d77e9d2023-02-09 21:58:181309 (
Peter Kastinge2c5ee82023-02-15 17:23:081310 'char8_t and std::u8string are not yet allowed. Can you use [unsigned]',
1311 ' char and std::string instead?',
1312 ),
1313 True,
Daniel Cheng893c563f2023-04-21 09:54:521314 [
1315 # The demangler does not use this type but needs to know about it.
1316 'base/third_party/symbolize/demangle\.cc',
1317 # Don't warn in third_party folders.
1318 _THIRD_PARTY_EXCEPT_BLINK
1319 ],
Peter Kastinge2c5ee82023-02-15 17:23:081320 ),
1321 BanRule(
1322 r'/(\b(co_await|co_return|co_yield)\b|#include <coroutine>)',
1323 (
1324 'Coroutines are not yet allowed (https://crbug.com/1403840).',
1325 ),
1326 True,
1327 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1328 ),
1329 BanRule(
Peter Kastingcc152522023-03-22 20:17:371330 r'/^\s*(export\s|import\s+["<:\w]|module(;|\s+[:\w]))',
Peter Kasting69357dc2023-03-14 01:34:291331 (
1332 'Modules are disallowed for now due to lack of toolchain support.',
1333 ),
1334 True,
1335 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1336 ),
1337 BanRule(
Peter Kasting8bc046d22023-11-14 00:38:031338 r'/\[\[(\w*::)?no_unique_address\]\]',
1339 (
1340 '[[no_unique_address]] does not work as expected on Windows ',
1341 '(https://crbug.com/1414621). Use NO_UNIQUE_ADDRESS instead.',
1342 ),
1343 True,
1344 [
Daniel Chenga04e0d22024-01-16 18:27:251345 # NO_UNIQUE_ADDRESS / PA_NO_UNIQUE_ADDRESS provide canonical access.
1346 r'^base/compiler_specific\.h',
1347 r'^base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific\.h',
Peter Kasting8bc046d22023-11-14 00:38:031348 # Not an error in third_party folders.
1349 _THIRD_PARTY_EXCEPT_BLINK,
1350 ],
1351 ),
1352 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081353 r'/#include <format>',
1354 (
1355 '<format> is not yet allowed. Use base::StringPrintf() instead.',
1356 ),
1357 True,
1358 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1359 ),
1360 BanRule(
1361 r'/#include <ranges>',
1362 (
1363 '<ranges> is not yet allowed. Use base/ranges/algorithm.h instead.',
1364 ),
1365 True,
1366 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1367 ),
1368 BanRule(
1369 r'/#include <source_location>',
1370 (
1371 '<source_location> is not yet allowed. Use base/location.h instead.',
1372 ),
1373 True,
1374 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1375 ),
1376 BanRule(
Nick Diego Yamanee522ae82024-02-27 04:23:221377 r'/\bstd::to_address\b',
1378 (
1379 'std::to_address is banned because it is not guaranteed to be',
Daniel Cheng364216a2024-05-07 20:25:431380 'SFINAE-compatible. Use base::to_address from base/types/to_address.h',
1381 'instead.',
Nick Diego Yamanee522ae82024-02-27 04:23:221382 ),
1383 True,
1384 [
1385 # Needed in base::to_address implementation.
1386 r'base/types/to_address.h',
1387 _THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1388 ),
1389 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081390 r'/#include <syncstream>',
1391 (
1392 '<syncstream> is banned.',
Peter Kasting6d77e9d2023-02-09 21:58:181393 ),
1394 True,
1395 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1396 ),
1397 BanRule(
Michael Giuffrida7f93d6922019-04-19 14:39:581398 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:191399 (
1400 'RunMessageLoop is deprecated, use RunLoop instead.',
1401 ),
1402 False,
1403 (),
1404 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151405 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441406 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:191407 (
1408 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
1409 "if you're convinced you need this.",
1410 ),
1411 False,
1412 (),
1413 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151414 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441415 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:191416 (
1417 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:041418 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:191419 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
1420 'async events instead of flushing threads.',
1421 ),
1422 False,
1423 (),
1424 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151425 BanRule(
Gabriel Charette147335ea2018-03-22 15:59:191426 r'MessageLoopRunner',
1427 (
1428 'MessageLoopRunner is deprecated, use RunLoop instead.',
1429 ),
1430 False,
1431 (),
1432 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151433 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441434 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:191435 (
1436 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
1437 "gab@ if you found a use case where this is the only solution.",
1438 ),
1439 False,
1440 (),
1441 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151442 BanRule(
Victor Costane48a2e82019-03-15 22:02:341443 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161444 (
Victor Costane48a2e82019-03-15 22:02:341445 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161446 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1447 ),
1448 True,
1449 (
1450 r'^sql/initialization\.(cc|h)$',
1451 r'^third_party/sqlite/.*\.(c|cc|h)$',
1452 ),
1453 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151454 BanRule(
Austin Sullivand661ab52022-11-16 08:55:151455 'CREATE VIEW',
1456 (
1457 'SQL views are disabled in Chromium feature code',
1458 'https://chromium.googlesource.com/chromium/src/+/HEAD/sql#no-views',
1459 ),
1460 True,
1461 (
1462 _THIRD_PARTY_EXCEPT_BLINK,
1463 # sql/ itself uses views when using memory-mapped IO.
1464 r'^sql/.*',
1465 # Various performance tools that do not build as part of Chrome.
1466 r'^infra/.*',
1467 r'^tools/perf.*',
1468 r'.*perfetto.*',
1469 ),
1470 ),
1471 BanRule(
1472 'CREATE VIRTUAL TABLE',
1473 (
1474 'SQL virtual tables are disabled in Chromium feature code',
1475 'https://chromium.googlesource.com/chromium/src/+/HEAD/sql#no-virtual-tables',
1476 ),
1477 True,
1478 (
1479 _THIRD_PARTY_EXCEPT_BLINK,
1480 # sql/ itself uses virtual tables in the recovery module and tests.
1481 r'^sql/.*',
1482 # TODO(https://crbug.com/695592): Remove once WebSQL is deprecated.
1483 r'third_party/blink/web_tests/storage/websql/.*'
1484 # Various performance tools that do not build as part of Chrome.
1485 r'^tools/perf.*',
1486 r'.*perfetto.*',
1487 ),
1488 ),
1489 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441490 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471491 (
1492 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1493 'base::RandomShuffle instead.'
1494 ),
1495 True,
1496 (),
1497 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151498 BanRule(
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241499 'ios/web/public/test/http_server',
1500 (
1501 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1502 ),
1503 False,
1504 (),
1505 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151506 BanRule(
Robert Liao764c9492019-01-24 18:46:281507 'GetAddressOf',
1508 (
1509 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Xiaohan Wangfb31b4cd2020-07-08 01:18:531510 'implicated in a few leaks. ReleaseAndGetAddressOf() is safe but ',
Joshua Berenhaus8b972ec2020-09-11 20:00:111511 'operator& is generally recommended. So always use operator& instead. ',
Xiaohan Wangfb31b4cd2020-07-08 01:18:531512 'See http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:281513 ),
1514 True,
1515 (),
1516 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151517 BanRule(
Ben Lewisa9514602019-04-29 17:53:051518 'SHFileOperation',
1519 (
1520 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1521 'complex functions to achieve the same goals. Use IFileOperation for ',
1522 'any esoteric actions instead.'
1523 ),
1524 True,
1525 (),
1526 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151527 BanRule(
Cliff Smolinsky81951642019-04-30 21:39:511528 'StringFromGUID2',
1529 (
1530 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
Jan Wilken Dörrieec815922020-07-22 07:46:241531 'Use base::win::WStringFromGUID instead.'
Cliff Smolinsky81951642019-04-30 21:39:511532 ),
1533 True,
1534 (
Daniel Chenga44a1bcd2022-03-15 20:00:151535 r'/base/win/win_util_unittest.cc',
Cliff Smolinsky81951642019-04-30 21:39:511536 ),
1537 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151538 BanRule(
Cliff Smolinsky81951642019-04-30 21:39:511539 'StringFromCLSID',
1540 (
1541 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
Jan Wilken Dörrieec815922020-07-22 07:46:241542 'Use base::win::WStringFromGUID instead.'
Cliff Smolinsky81951642019-04-30 21:39:511543 ),
1544 True,
1545 (
Daniel Chenga44a1bcd2022-03-15 20:00:151546 r'/base/win/win_util_unittest.cc',
Cliff Smolinsky81951642019-04-30 21:39:511547 ),
1548 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151549 BanRule(
Avi Drissman7382afa02019-04-29 23:27:131550 'kCFAllocatorNull',
1551 (
1552 'The use of kCFAllocatorNull with the NoCopy creation of ',
1553 'CoreFoundation types is prohibited.',
1554 ),
1555 True,
1556 (),
1557 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151558 BanRule(
Oksana Zhuravlovafd247772019-05-16 16:57:291559 'mojo::ConvertTo',
1560 (
1561 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1562 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1563 'StringTraits if you would like to convert between custom types and',
1564 'the wire format of mojom types.'
1565 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221566 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291567 (
David Dorwin13dc48b2022-06-03 21:18:421568 r'^fuchsia_web/webengine/browser/url_request_rewrite_rules_manager\.cc$',
1569 r'^fuchsia_web/webengine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291570 r'^third_party/blink/.*\.(cc|h)$',
1571 r'^content/renderer/.*\.(cc|h)$',
1572 ),
1573 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151574 BanRule(
Oksana Zhuravlovac8222d22019-12-19 19:21:161575 'GetInterfaceProvider',
1576 (
1577 'InterfaceProvider is deprecated.',
1578 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1579 'or Platform::GetBrowserInterfaceBroker.'
1580 ),
1581 False,
1582 (),
1583 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151584 BanRule(
Robert Liao1d78df52019-11-11 20:02:011585 'CComPtr',
1586 (
1587 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1588 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1589 'details.'
1590 ),
1591 False,
1592 (),
1593 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151594 BanRule(
Xiaohan Wang72bd2ba2020-02-18 21:38:201595 r'/\b(IFACE|STD)METHOD_?\(',
1596 (
1597 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1598 'Instead, always use IFACEMETHODIMP in the declaration.'
1599 ),
1600 False,
1601 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1602 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151603 BanRule(
Allen Bauer53b43fb12020-03-12 17:21:471604 'set_owned_by_client',
1605 (
1606 'set_owned_by_client is deprecated.',
1607 'views::View already owns the child views by default. This introduces ',
1608 'a competing ownership model which makes the code difficult to reason ',
1609 'about. See http://crbug.com/1044687 for more details.'
1610 ),
1611 False,
1612 (),
1613 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151614 BanRule(
Peter Boström7ff41522021-07-29 03:43:271615 'RemoveAllChildViewsWithoutDeleting',
1616 (
1617 'RemoveAllChildViewsWithoutDeleting is deprecated.',
1618 'This method is deemed dangerous as, unless raw pointers are re-added,',
1619 'calls to this method introduce memory leaks.'
1620 ),
1621 False,
1622 (),
1623 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151624 BanRule(
Eric Secklerbe6f48d2020-05-06 18:09:121625 r'/\bTRACE_EVENT_ASYNC_',
1626 (
1627 'Please use TRACE_EVENT_NESTABLE_ASYNC_.. macros instead',
1628 'of TRACE_EVENT_ASYNC_.. (crbug.com/1038710).',
1629 ),
1630 False,
1631 (
1632 r'^base/trace_event/.*',
1633 r'^base/tracing/.*',
1634 ),
1635 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151636 BanRule(
Aditya Kushwah5a286b72022-02-10 04:54:431637 r'/\bbase::debug::DumpWithoutCrashingUnthrottled[(][)]',
1638 (
1639 'base::debug::DumpWithoutCrashingUnthrottled() does not throttle',
1640 'dumps and may spam crash reports. Consider if the throttled',
1641 'variants suffice instead.',
1642 ),
1643 False,
1644 (),
1645 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151646 BanRule(
Robert Liao22f66a52021-04-10 00:57:521647 'RoInitialize',
1648 (
Robert Liao48018922021-04-16 23:03:021649 'Improper use of [base::win]::RoInitialize() has been implicated in a ',
Robert Liao22f66a52021-04-10 00:57:521650 'few COM initialization leaks. Use base::win::ScopedWinrtInitializer ',
1651 'instead. See http://crbug.com/1197722 for more information.'
1652 ),
1653 True,
Robert Liao48018922021-04-16 23:03:021654 (
Bruce Dawson40fece62022-09-16 19:58:311655 r'^base/win/scoped_winrt_initializer\.cc$',
Danil Chapovalov07694382023-05-24 17:55:211656 r'^third_party/abseil-cpp/absl/.*',
Robert Liao48018922021-04-16 23:03:021657 ),
Robert Liao22f66a52021-04-10 00:57:521658 ),
Patrick Monettec343bb982022-06-01 17:18:451659 BanRule(
1660 r'base::Watchdog',
1661 (
1662 'base::Watchdog is deprecated because it creates its own thread.',
1663 'Instead, manually start a timer on a SequencedTaskRunner.',
1664 ),
1665 False,
1666 (),
1667 ),
Andrew Rayskiy04a51ce2022-06-07 11:47:091668 BanRule(
1669 'base::Passed',
1670 (
1671 'Do not use base::Passed. It is a legacy helper for capturing ',
1672 'move-only types with base::BindRepeating, but invoking the ',
1673 'resulting RepeatingCallback moves the captured value out of ',
1674 'the callback storage, and subsequent invocations may pass the ',
1675 'value in a valid but undefined state. Prefer base::BindOnce().',
1676 'See http://crbug.com/1326449 for context.'
1677 ),
1678 False,
Daniel Cheng91f6fbaf2022-09-16 12:07:481679 (
1680 # False positive, but it is also fine to let bind internals reference
1681 # base::Passed.
Daniel Chengcd23b8b2022-09-16 17:16:241682 r'^base[\\/]functional[\\/]bind\.h',
Daniel Cheng91f6fbaf2022-09-16 12:07:481683 r'^base[\\/]functional[\\/]bind_internal\.h',
1684 ),
Andrew Rayskiy04a51ce2022-06-07 11:47:091685 ),
Daniel Cheng2248b332022-07-27 06:16:591686 BanRule(
Daniel Chengba3bc2e2022-10-03 02:45:431687 r'base::Feature k',
1688 (
1689 'Please use BASE_DECLARE_FEATURE() or BASE_FEATURE() instead of ',
1690 'directly declaring/defining features.'
1691 ),
1692 True,
1693 [
Daniel Chengb000a8c2023-12-08 04:37:281694 # Implements BASE_DECLARE_FEATURE().
1695 r'^base/feature_list\.h',
Daniel Chengba3bc2e2022-10-03 02:45:431696 ],
1697 ),
Robert Ogden92101dcb2022-10-19 23:49:361698 BanRule(
Arthur Sonzogni1da65fa2023-03-27 16:01:521699 r'/\bchartorune\b',
Robert Ogden92101dcb2022-10-19 23:49:361700 (
1701 'chartorune is not memory-safe, unless you can guarantee the input ',
1702 'string is always null-terminated. Otherwise, please use charntorune ',
1703 'from libphonenumber instead.'
1704 ),
1705 True,
1706 [
1707 _THIRD_PARTY_EXCEPT_BLINK,
1708 # Exceptions to this rule should have a fuzzer.
1709 ],
1710 ),
Arthur Sonzogni1da65fa2023-03-27 16:01:521711 BanRule(
1712 r'/\b#include "base/atomicops\.h"\b',
1713 (
1714 'Do not use base::subtle atomics, but std::atomic, which are simpler '
1715 'to use, have better understood, clearer and richer semantics, and are '
1716 'harder to mis-use. See details in base/atomicops.h.',
1717 ),
1718 False,
1719 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Benoit Lize79cf0592023-01-27 10:01:571720 ),
Arthur Sonzogni60348572e2023-04-07 10:22:521721 BanRule(
1722 r'CrossThreadPersistent<',
1723 (
1724 'Do not use blink::CrossThreadPersistent, but '
1725 'blink::CrossThreadHandle. It is harder to mis-use.',
1726 'More info: '
1727 'https://docs.google.com/document/d/1GIT0ysdQ84sGhIo1r9EscF_fFt93lmNVM_q4vvHj2FQ/edit#heading=h.3e4d6y61tgs',
1728 'Please contact platform-architecture-dev@ before adding new instances.'
1729 ),
1730 False,
1731 []
1732 ),
1733 BanRule(
1734 r'CrossThreadWeakPersistent<',
1735 (
1736 'Do not use blink::CrossThreadWeakPersistent, but '
1737 'blink::CrossThreadWeakHandle. It is harder to mis-use.',
1738 'More info: '
1739 'https://docs.google.com/document/d/1GIT0ysdQ84sGhIo1r9EscF_fFt93lmNVM_q4vvHj2FQ/edit#heading=h.3e4d6y61tgs',
1740 'Please contact platform-architecture-dev@ before adding new instances.'
1741 ),
1742 False,
1743 []
1744 ),
Avi Drissman491617c2023-04-13 17:33:151745 BanRule(
1746 r'objc/objc.h',
1747 (
1748 'Do not include <objc/objc.h>. It defines away ARC lifetime '
1749 'annotations, and is thus dangerous.',
1750 'Please use the pimpl pattern; search for `ObjCStorage` for examples.',
1751 'For further reading on how to safely mix C++ and Obj-C, see',
1752 'https://chromium.googlesource.com/chromium/src/+/main/docs/mac/mixing_cpp_and_objc.md'
1753 ),
1754 True,
1755 []
1756 ),
Grace Park8d59b54b2023-04-26 17:53:351757 BanRule(
1758 r'/#include <filesystem>',
1759 (
1760 'libc++ <filesystem> is banned per the Google C++ styleguide.',
1761 ),
1762 True,
1763 # This fuzzing framework is a standalone open source project and
1764 # cannot rely on Chromium base.
1765 (r'third_party/centipede'),
1766 ),
Daniel Cheng72153e02023-05-18 21:18:141767 BanRule(
1768 r'TopDocument()',
1769 (
1770 'TopDocument() does not work correctly with out-of-process iframes. '
1771 'Please do not introduce new uses.',
1772 ),
1773 True,
1774 (
1775 # TODO(crbug.com/617677): Remove all remaining uses.
1776 r'^third_party/blink/renderer/core/dom/document\.cc',
1777 r'^third_party/blink/renderer/core/dom/document\.h',
1778 r'^third_party/blink/renderer/core/dom/element\.cc',
1779 r'^third_party/blink/renderer/core/exported/web_disallow_transition_scope_test\.cc',
1780 r'^third_party/blink/renderer/core/exported/web_document_test\.cc',
Daniel Cheng72153e02023-05-18 21:18:141781 r'^third_party/blink/renderer/core/html/html_anchor_element\.cc',
1782 r'^third_party/blink/renderer/core/html/html_dialog_element\.cc',
1783 r'^third_party/blink/renderer/core/html/html_element\.cc',
1784 r'^third_party/blink/renderer/core/html/html_frame_owner_element\.cc',
1785 r'^third_party/blink/renderer/core/html/media/video_wake_lock\.cc',
1786 r'^third_party/blink/renderer/core/loader/anchor_element_interaction_tracker\.cc',
1787 r'^third_party/blink/renderer/core/page/scrolling/root_scroller_controller\.cc',
1788 r'^third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller\.cc',
1789 r'^third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller\.h',
1790 r'^third_party/blink/renderer/core/script/classic_pending_script\.cc',
1791 r'^third_party/blink/renderer/core/script/script_loader\.cc',
1792 ),
1793 ),
Arthur Sonzognif0eea302023-08-18 19:20:311794 BanRule(
1795 pattern = r'base::raw_ptr<',
1796 explanation = (
1797 'Do not use base::raw_ptr, use raw_ptr.',
1798 ),
1799 treat_as_error = True,
1800 excluded_paths = (
1801 '^base/',
1802 '^tools/',
1803 ),
1804 ),
1805 BanRule(
1806 pattern = r'base:raw_ref<',
1807 explanation = (
1808 'Do not use base::raw_ref, use raw_ref.',
1809 ),
1810 treat_as_error = True,
1811 excluded_paths = (
1812 '^base/',
1813 '^tools/',
1814 ),
1815 ),
Anton Maliev66751812023-08-24 16:28:131816 BanRule(
Tom Sepez41eb158d2023-09-12 16:16:221817 pattern = r'/raw_ptr<[^;}]*\w{};',
1818 explanation = (
1819 'Do not use {} for raw_ptr initialization, use = nullptr instead.',
1820 ),
1821 treat_as_error = True,
1822 excluded_paths = (
1823 '^base/',
1824 '^tools/',
1825 ),
1826 ),
1827 BanRule(
Arthur Sonzogni48c6aea22023-09-04 22:25:201828 pattern = r'/#include "base/allocator/.*/raw_'
1829 r'(ptr|ptr_cast|ptr_exclusion|ref).h"',
1830 explanation = (
1831 'Please include the corresponding facade headers:',
1832 '- #include "base/memory/raw_ptr.h"',
1833 '- #include "base/memory/raw_ptr_cast.h"',
1834 '- #include "base/memory/raw_ptr_exclusion.h"',
1835 '- #include "base/memory/raw_ref.h"',
1836 ),
1837 treat_as_error = True,
1838 excluded_paths = (
1839 '^base/',
1840 '^tools/',
1841 ),
1842 ),
1843 BanRule(
Anton Maliev66751812023-08-24 16:28:131844 pattern = r'ContentSettingsType::COOKIES',
1845 explanation = (
1846 'Do not use ContentSettingsType::COOKIES to check whether cookies are '
1847 'supported in the provided context. Instead rely on the '
1848 'content_settings::CookieSettings API. If you are using '
1849 'ContentSettingsType::COOKIES to check the user preference setting '
1850 'specifically, disregard this warning.',
1851 ),
1852 treat_as_error = False,
1853 excluded_paths = (
1854 '^chrome/browser/ui/content_settings/',
1855 '^components/content_settings/',
Christian Dullweber61416642023-10-05 11:46:431856 '^services/network/cookie_settings.cc',
1857 '.*test.cc',
Anton Maliev66751812023-08-24 16:28:131858 ),
1859 ),
Tom Andersoncd522072023-10-03 00:52:351860 BanRule(
Michelle Abreo6b7437822024-04-26 17:29:041861 pattern = r'ContentSettingsType::TRACKING_PROTECTION',
1862 explanation = (
1863 'Do not directly use ContentSettingsType::TRACKING_PROTECTION to check '
1864 'for tracking protection exceptions. Instead rely on the '
Fiona Macintosh025ab452024-05-15 21:11:581865 'privacy_sandbox::TrackingProtectionSettings API.',
Michelle Abreo6b7437822024-04-26 17:29:041866 ),
1867 treat_as_error = False,
1868 excluded_paths = (
1869 '^chrome/browser/ui/content_settings/',
1870 '^components/content_settings/',
1871 '^components/privacy_sandbox/tracking_protection_settings.cc',
1872 '.*test.cc',
1873 ),
1874 ),
1875 BanRule(
Tom Anderson11e4a732024-02-12 23:57:221876 pattern = r'/\bg_signal_connect',
Tom Andersoncd522072023-10-03 00:52:351877 explanation = (
1878 'Use ScopedGSignal instead of g_signal_connect*()',
1879 ),
1880 treat_as_error = True,
1881 excluded_paths = (
1882 '^ui/base/glib/scoped_gsignal.h',
1883 ),
1884 ),
Christian Flach8da3bf82023-10-12 09:42:531885 BanRule(
1886 pattern = r'features::kIsolatedWebApps',
1887 explanation = (
1888 'Do not use `features::kIsolatedWebApps` directly to guard Isolated ',
1889 'Web App code. ',
1890 'Use `content::IsolatedWebAppsPolicy::AreIsolatedWebAppsEnabled()` in ',
1891 'the browser process or check the `kEnableIsolatedWebAppsInRenderer` ',
1892 'command line flag in the renderer process.',
1893 ),
1894 treat_as_error = True,
1895 excluded_paths = _TEST_CODE_EXCLUDED_PATHS + (
1896 '^chrome/browser/about_flags.cc',
Andrew Rayskiy93a6b0b32024-03-08 00:04:331897 '^chrome/browser/web_applications/isolated_web_apps/chrome_content_browser_client_isolated_web_apps_part.cc',
Christian Flach8da3bf82023-10-12 09:42:531898 '^chrome/browser/ui/startup/bad_flags_prompt.cc',
1899 '^content/shell/browser/shell_content_browser_client.cc'
1900 )
1901 ),
Arthur Sonzogni5cbd3e32024-02-08 17:51:321902 BanRule(
Andrew Rayskiycdd45e732024-03-20 14:32:391903 pattern = r'features::kIsolatedWebAppDevMode',
1904 explanation = (
1905 'Do not use `features::kIsolatedWebAppDevMode` directly to guard code ',
1906 'related to Isolated Web App Developer Mode. ',
1907 'Use `web_app::IsIwaDevModeEnabled()` instead.',
1908 ),
1909 treat_as_error = True,
1910 excluded_paths = _TEST_CODE_EXCLUDED_PATHS + (
1911 '^chrome/browser/about_flags.cc',
1912 '^chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.cc',
1913 '^chrome/browser/ui/startup/bad_flags_prompt.cc',
1914 )
1915 ),
1916 BanRule(
1917 pattern = r'features::kIsolatedWebAppUnmanagedInstall',
1918 explanation = (
1919 'Do not use `features::kIsolatedWebAppUnmanagedInstall` directly to ',
1920 'guard code related to unmanaged install flow for Isolated Web Apps. ',
1921 'Use `web_app::IsIwaUnmanagedInstallEnabled()` instead.',
1922 ),
1923 treat_as_error = True,
1924 excluded_paths = _TEST_CODE_EXCLUDED_PATHS + (
1925 '^chrome/browser/about_flags.cc',
1926 '^chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.cc',
1927 )
1928 ),
1929 BanRule(
Arthur Sonzognia9dd4a7b2024-02-13 08:07:271930 pattern = r'/\babsl::(optional|nullopt|make_optional|in_place|in_place_t)\b',
Arthur Sonzogni5cbd3e32024-02-08 17:51:321931 explanation = (
Helmut Januschkab3f71ab52024-03-12 02:48:051932 'Don\'t use `absl::optional`. Use `std::optional`.',
Arthur Sonzogni5cbd3e32024-02-08 17:51:321933 ),
1934 # TODO(b/40288126): Enforce after completing the rewrite.
1935 treat_as_error = False,
1936 excluded_paths = [
1937 _THIRD_PARTY_EXCEPT_BLINK,
1938 ]
1939 ),
Helmut Januschkab3f71ab52024-03-12 02:48:051940 BanRule(
1941 pattern = r'(base::)?\bStringPiece\b',
1942 explanation = (
1943 'Don\'t use `base::StringPiece`. Use `std::string_view`.',
1944 ),
1945 treat_as_error = False,
1946 ),
1947 BanRule(
1948 pattern = r'(base::)?\bStringPiece16\b',
1949 explanation = (
1950 'Don\'t use `base::StringPiece16`. Use `std::u16string_view`.',
1951 ),
1952 treat_as_error = False,
1953 ),
Benjamin Beaudrycaf15b82024-03-28 22:05:221954 BanRule(
1955 pattern = '/(CUIAutomation|AccessibleObjectFromWindow)',
1956 explanation = (
1957 'Direct usage of UIAutomation or IAccessible2 in client code is '
1958 'discouraged in Chromium, as it is not an assistive technology and '
1959 'should not rely on accessibility APIs directly. These APIs can '
1960 'introduce significant performance overhead. However, if you believe '
1961 'your use case warrants an exception, please discuss it with an '
1962 'accessibility owner before proceeding. For more information on the '
1963 'performance implications, see https://docs.google.com/document/d/1jN4itpCe_bDXF0BhFaYwv4xVLsCWkL9eULdzjmLzkuk/edit#heading=h.pwth3nbwdub0.',
1964 ),
1965 treat_as_error = False,
1966 ),
Allen Bauer5839eb22024-05-28 20:20:061967 BanRule(
1968 pattern = r'/WIDGET_OWNS_NATIVE_WIDGET|'
1969 r'NATIVE_WIDGET_OWNS_WIDGET',
1970 explanation = (
1971 'WIDGET_OWNS_NATIVE_WIDGET and NATIVE_WIDGET_OWNS_WIDGET are in the '
1972 'process of being deprecated. Consider using the new '
1973 'CLIENT_OWNS_WIDGET ownership model. Eventually, this will be the only '
1974 'available ownership model available and the associated enumeration'
1975 'will be removed.',
1976 ),
1977 treat_as_error = False,
1978 ),
[email protected]127f18ec2012-06-16 05:05:591979)
1980
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:151981_DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING = (
1982 'Used a predicate related to signin::ConsentLevel::kSync which will always '
1983 'return false in the future (crbug.com/40066949). Prefer using a predicate '
1984 'that also supports signin::ConsentLevel::kSignin when appropriate. It is '
1985 'safe to ignore this warning if you are just moving an existing call, or if '
1986 'you want special handling for users in the legacy state. In doubt, reach '
1987 'out to //components/sync/OWNERS.'
1988)
1989
1990# C++ functions related to signin::ConsentLevel::kSync which are deprecated.
1991_DEPRECATED_SYNC_CONSENT_CPP_FUNCTIONS : Sequence[BanRule] = (
1992 BanRule(
1993 'HasSyncConsent',
1994 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
1995 False,
1996 ),
1997 BanRule(
1998 'CanSyncFeatureStart',
1999 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2000 False,
2001 ),
2002 BanRule(
2003 'IsSyncFeatureEnabled',
2004 (
2005 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2006 ),
2007 False,
2008 ),
2009 BanRule(
2010 'IsSyncFeatureActive',
2011 (
2012 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2013 ),
2014 False,
2015 ),
2016)
2017
2018# Java functions related to signin::ConsentLevel::kSync which are deprecated.
2019_DEPRECATED_SYNC_CONSENT_JAVA_FUNCTIONS : Sequence[BanRule] = (
2020 BanRule(
2021 'hasSyncConsent',
2022 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2023 False,
2024 ),
2025 BanRule(
2026 'canSyncFeatureStart',
2027 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2028 False,
2029 ),
2030 BanRule(
2031 'isSyncFeatureEnabled',
2032 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2033 False,
2034 ),
2035 BanRule(
2036 'isSyncFeatureActive',
2037 _DEPRECATED_SYNC_CONSENT_FUNCTION_WARNING,
2038 False,
2039 ),
2040)
2041
Daniel Cheng92c15e32022-03-16 17:48:222042_BANNED_MOJOM_PATTERNS : Sequence[BanRule] = (
2043 BanRule(
2044 'handle<shared_buffer>',
2045 (
2046 'Please use one of the more specific shared memory types instead:',
2047 ' mojo_base.mojom.ReadOnlySharedMemoryRegion',
2048 ' mojo_base.mojom.WritableSharedMemoryRegion',
2049 ' mojo_base.mojom.UnsafeSharedMemoryRegion',
2050 ),
2051 True,
2052 ),
2053)
2054
mlamouria82272622014-09-16 18:45:042055_IPC_ENUM_TRAITS_DEPRECATED = (
2056 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:502057 'See http://www.chromium.org/Home/chromium-security/education/'
2058 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:042059
Stephen Martinis97a394142018-06-07 23:06:052060_LONG_PATH_ERROR = (
2061 'Some files included in this CL have file names that are too long (> 200'
2062 ' characters). If committed, these files will cause issues on Windows. See'
2063 ' https://crbug.com/612667 for more details.'
2064)
2065
Shenghua Zhangbfaa38b82017-11-16 21:58:022066_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Bruce Dawson40fece62022-09-16 19:58:312067 r".*/AppHooksImpl\.java",
2068 r".*/BuildHooksAndroidImpl\.java",
2069 r".*/LicenseContentProvider\.java",
2070 r".*/PlatformServiceBridgeImpl.java",
2071 r".*chrome/android/feed/dummy/.*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:022072]
[email protected]127f18ec2012-06-16 05:05:592073
Mohamed Heikald048240a2019-11-12 16:57:372074# List of image extensions that are used as resources in chromium.
2075_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
2076
Sean Kau46e29bc2017-08-28 16:31:162077# These paths contain test data and other known invalid JSON files.
Erik Staab2dd72b12020-04-16 15:03:402078_KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS = [
Bruce Dawson40fece62022-09-16 19:58:312079 r'test/data/',
2080 r'testing/buildbot/',
2081 r'^components/policy/resources/policy_templates\.json$',
2082 r'^third_party/protobuf/',
Camillo Bruni1411a352023-05-24 12:39:032083 r'^third_party/blink/perf_tests/speedometer.*/resources/todomvc/learn\.json',
Bruce Dawson40fece62022-09-16 19:58:312084 r'^third_party/blink/renderer/devtools/protocol\.json$',
2085 r'^third_party/blink/web_tests/external/wpt/',
2086 r'^tools/perf/',
2087 r'^tools/traceline/svgui/startup-release.json',
Daniel Cheng2d4c2d192022-07-01 01:38:312088 # vscode configuration files allow comments
Bruce Dawson40fece62022-09-16 19:58:312089 r'^tools/vscode/',
Sean Kau46e29bc2017-08-28 16:31:162090]
2091
Andrew Grieveb773bad2020-06-05 18:00:382092# These are not checked on the public chromium-presubmit trybot.
2093# Add files here that rely on .py files that exists only for target_os="android"
Samuel Huangc2f5d6bb2020-08-17 23:46:042094# checkouts.
agrievef32bcc72016-04-04 14:57:402095_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Grieveb773bad2020-06-05 18:00:382096 'chrome/android/features/create_stripped_java_factory.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:382097]
2098
2099
2100_GENERIC_PYDEPS_FILES = [
Bruce Dawson853b739e62022-05-03 23:03:102101 'android_webview/test/components/run_webview_component_smoketest.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042102 'android_webview/tools/run_cts.pydeps',
Andrew Grieve4c4cede2020-11-20 22:09:362103 'build/android/apk_operations.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042104 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362105 'build/android/gyp/aar.pydeps',
2106 'build/android/gyp/aidl.pydeps',
2107 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:382108 'build/android/gyp/assert_static_initializers.pydeps',
Mohamed Heikal133e1f22023-04-18 20:04:372109 'build/android/gyp/binary_baseline_profile.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362110 'build/android/gyp/bytecode_processor.pydeps',
Robbie McElrath360e54d2020-11-12 20:38:022111 'build/android/gyp/bytecode_rewriter.pydeps',
Mohamed Heikal6305bcc2021-03-15 15:34:222112 'build/android/gyp/check_flag_expectations.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:112113 'build/android/gyp/compile_java.pydeps',
Peter Weneaa963f2023-01-20 19:40:302114 'build/android/gyp/compile_kt.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362115 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362116 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362117 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:112118 'build/android/gyp/create_app_bundle.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042119 'build/android/gyp/create_app_bundle_apks.pydeps',
2120 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362121 'build/android/gyp/create_java_binary_script.pydeps',
Mohamed Heikaladbe4e482020-07-09 19:25:122122 'build/android/gyp/create_r_java.pydeps',
Mohamed Heikal8cd763a52021-02-01 23:32:092123 'build/android/gyp/create_r_txt.pydeps',
Andrew Grieveb838d832019-02-11 16:55:222124 'build/android/gyp/create_size_info_files.pydeps',
Peter Wene6e017e2022-07-27 21:40:402125 'build/android/gyp/create_test_apk_wrapper_script.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:002126 'build/android/gyp/create_ui_locale_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362127 'build/android/gyp/dex.pydeps',
2128 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362129 'build/android/gyp/filter_zip.pydeps',
Mohamed Heikal21e1994b2021-11-12 21:37:212130 'build/android/gyp/flatc_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362131 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:362132 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362133 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:582134 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362135 'build/android/gyp/java_cpp_enum.pydeps',
Nate Fischerac07b2622020-10-01 20:20:142136 'build/android/gyp/java_cpp_features.pydeps',
Ian Vollickb99472e2019-03-07 21:35:262137 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve09457912021-04-27 15:22:472138 'build/android/gyp/java_google_api_keys.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042139 'build/android/gyp/jinja_template.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362140 'build/android/gyp/lint.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362141 'build/android/gyp/merge_manifest.pydeps',
Bruce Dawson853b739e62022-05-03 23:03:102142 'build/android/gyp/optimize_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362143 'build/android/gyp/prepare_resources.pydeps',
Mohamed Heikalf85138b2020-10-06 15:43:222144 'build/android/gyp/process_native_prebuilt.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362145 'build/android/gyp/proguard.pydeps',
Andrew Grievee3a775ab2022-05-16 15:59:222146 'build/android/gyp/system_image_apks.pydeps',
Bruce Dawson853b739e62022-05-03 23:03:102147 'build/android/gyp/trace_event_bytecode_rewriter.pydeps',
Peter Wen578730b2020-03-19 19:55:462148 'build/android/gyp/turbine.pydeps',
Mohamed Heikal246710c2021-06-14 15:34:302149 'build/android/gyp/unused_resources.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:242150 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362151 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:462152 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:562153 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362154 'build/android/incremental_install/generate_android_manifest.pydeps',
2155 'build/android/incremental_install/write_installer_json.pydeps',
Stephanie Kim392913b452022-06-15 17:25:322156 'build/android/pylib/results/presentation/test_results_presentation.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042157 'build/android/resource_sizes.pydeps',
2158 'build/android/test_runner.pydeps',
2159 'build/android/test_wrapper/logdog_wrapper.pydeps',
Samuel Huange65eb3f12020-08-14 19:04:362160 'build/lacros/lacros_resource_sizes.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:362161 'build/protoc_java.pydeps',
Peter Kotwicz64667b02020-10-18 06:43:322162 'chrome/android/monochrome/scripts/monochrome_python_tests.pydeps',
Peter Wenefb56c72020-06-04 15:12:272163 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
2164 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Junbo Kedcd3a452021-03-19 17:55:042165 'chromecast/resource_sizes/chromecast_resource_sizes.pydeps',
Mohannad Farrag19102742023-12-01 01:16:302166 'components/cronet/tools/check_combined_proguard_file.pydeps',
2167 'components/cronet/tools/generate_proguard_file.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:002168 'components/cronet/tools/generate_javadoc.pydeps',
2169 'components/cronet/tools/jar_src.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:382170 'components/module_installer/android/module_desc_java.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:002171 'content/public/android/generate_child_service.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:382172 'net/tools/testserver/testserver.pydeps',
Peter Kotwicz3c339f32020-10-19 19:59:182173 'testing/scripts/run_isolated_script_test.pydeps',
Stephanie Kimc94072c2022-03-22 22:31:412174 'testing/merge_scripts/standard_isolated_script_merge.pydeps',
2175 'testing/merge_scripts/standard_gtest_merge.pydeps',
2176 'testing/merge_scripts/code_coverage/merge_results.pydeps',
2177 'testing/merge_scripts/code_coverage/merge_steps.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042178 'third_party/android_platform/development/scripts/stack.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:422179 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
Yuki Shiino38eeaad12022-08-11 06:40:252180 'third_party/blink/renderer/bindings/scripts/check_generated_file_list.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:422181 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:132182 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Yuki Shiinoea477d32023-08-21 06:24:342183 'third_party/blink/renderer/bindings/scripts/generate_event_interface_names.pydeps',
Canon Mukaif32f8f592021-04-23 18:56:502184 'third_party/blink/renderer/bindings/scripts/validate_web_idl.pydeps',
Stephanie Kimc94072c2022-03-22 22:31:412185 'third_party/blink/tools/blinkpy/web_tests/merge_results.pydeps',
2186 'third_party/blink/tools/merge_web_test_results.pydeps',
John Budorickbc3571aa2019-04-25 02:20:062187 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:222188 'tools/binary_size/supersize.pydeps',
Ben Pastene028104a2022-08-10 19:17:452189 'tools/perf/process_perf_results.pydeps',
agrievef32bcc72016-04-04 14:57:402190]
2191
wnwenbdc444e2016-05-25 13:44:152192
agrievef32bcc72016-04-04 14:57:402193_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
2194
2195
Eric Boren6fd2b932018-01-25 15:05:082196# Bypass the AUTHORS check for these accounts.
2197_KNOWN_ROBOTS = set(
nqmtuan918b2232024-04-11 23:09:552198 ) | set('%[email protected]' % s for s in ('findit-for-me', 'luci-bisection')
Achuith Bhandarkar35905562018-07-25 19:28:452199 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:592200 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:522201 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
Sven Zhengf7abd31d2021-08-09 19:06:232202 'wpt-autoroller', 'chrome-weblayer-builder',
Garrett Beaty4d4fcf62021-11-24 17:57:472203 'lacros-version-skew-roller', 'skylab-test-cros-roller',
Sven Zheng722960ba2022-07-18 16:40:462204 'infra-try-recipes-tester', 'lacros-tracking-roller',
Brian Sheedy1c951e62022-10-27 01:16:182205 'lacros-sdk-version-roller', 'chrome-automated-expectation',
Stephanie Kimb49bdd242023-04-28 16:46:042206 'chromium-automated-expectation', 'chrome-branch-day',
2207 'chromium-autosharder')
Eric Boren835d71f2018-09-07 21:09:042208 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:272209 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:042210 ) | set('%[email protected]' % s
Yulan Lineb0cfba2021-04-09 18:43:162211 for s in ('chromium-internal-autoroll',)
Kyungjun Lee3b7c9352024-04-02 23:59:142212 ) | set('%[email protected]' % s
2213 for s in ('chrome-screen-ai-releaser',)
Yulan Lineb0cfba2021-04-09 18:43:162214 ) | set('%[email protected]' % s
Chong Gub277e342022-10-15 03:30:552215 for s in ('swarming-tasks',)
2216 ) | set('%[email protected]' % s
2217 for s in ('global-integration-try-builder',
Joey Scarr1103c5d2023-09-14 01:17:552218 'global-integration-ci-builder')
Suma Kasa3b9cf7a2023-09-21 22:05:542219 ) | set('%[email protected]' % s
2220 for s in ('chops-security-borg',
2221 'chops-security-cronjobs-cpesuggest'))
Eric Boren6fd2b932018-01-25 15:05:082222
Matt Stark6ef08872021-07-29 01:21:462223_INVALID_GRD_FILE_LINE = [
2224 (r'<file lang=.* path=.*', 'Path should come before lang in GRD files.')
2225]
Eric Boren6fd2b932018-01-25 15:05:082226
Daniel Bratell65b033262019-04-23 08:17:062227def _IsCPlusPlusFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502228 """Returns True if this file contains C++-like code (and not Python,
2229 Go, Java, MarkDown, ...)"""
Daniel Bratell65b033262019-04-23 08:17:062230
Sam Maiera6e76d72022-02-11 21:43:502231 ext = input_api.os_path.splitext(file_path)[1]
2232 # This list is compatible with CppChecker.IsCppFile but we should
2233 # consider adding ".c" to it. If we do that we can use this function
2234 # at more places in the code.
2235 return ext in (
2236 '.h',
2237 '.cc',
2238 '.cpp',
2239 '.m',
2240 '.mm',
2241 )
2242
Daniel Bratell65b033262019-04-23 08:17:062243
2244def _IsCPlusPlusHeaderFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502245 return input_api.os_path.splitext(file_path)[1] == ".h"
Daniel Bratell65b033262019-04-23 08:17:062246
2247
2248def _IsJavaFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502249 return input_api.os_path.splitext(file_path)[1] == ".java"
Daniel Bratell65b033262019-04-23 08:17:062250
2251
2252def _IsProtoFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502253 return input_api.os_path.splitext(file_path)[1] == ".proto"
Daniel Bratell65b033262019-04-23 08:17:062254
Mohamed Heikal5e5b7922020-10-29 18:57:592255
Erik Staabc734cd7a2021-11-23 03:11:522256def _IsXmlOrGrdFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502257 ext = input_api.os_path.splitext(file_path)[1]
2258 return ext in ('.grd', '.xml')
Erik Staabc734cd7a2021-11-23 03:11:522259
2260
Sven Zheng76a79ea2022-12-21 21:25:242261def _IsMojomFile(input_api, file_path):
2262 return input_api.os_path.splitext(file_path)[1] == ".mojom"
2263
2264
Mohamed Heikal5e5b7922020-10-29 18:57:592265def CheckNoUpstreamDepsOnClank(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502266 """Prevent additions of dependencies from the upstream repo on //clank."""
2267 # clank can depend on clank
2268 if input_api.change.RepositoryRoot().endswith('clank'):
2269 return []
2270 build_file_patterns = [
2271 r'(.+/)?BUILD\.gn',
2272 r'.+\.gni',
2273 ]
2274 excluded_files = [r'build[/\\]config[/\\]android[/\\]config\.gni']
2275 bad_pattern = input_api.re.compile(r'^[^#]*//clank')
Mohamed Heikal5e5b7922020-10-29 18:57:592276
Sam Maiera6e76d72022-02-11 21:43:502277 error_message = 'Disallowed import on //clank in an upstream build file:'
Mohamed Heikal5e5b7922020-10-29 18:57:592278
Sam Maiera6e76d72022-02-11 21:43:502279 def FilterFile(affected_file):
2280 return input_api.FilterSourceFile(affected_file,
2281 files_to_check=build_file_patterns,
2282 files_to_skip=excluded_files)
Mohamed Heikal5e5b7922020-10-29 18:57:592283
Sam Maiera6e76d72022-02-11 21:43:502284 problems = []
2285 for f in input_api.AffectedSourceFiles(FilterFile):
2286 local_path = f.LocalPath()
2287 for line_number, line in f.ChangedContents():
2288 if (bad_pattern.search(line)):
2289 problems.append('%s:%d\n %s' %
2290 (local_path, line_number, line.strip()))
2291 if problems:
2292 return [output_api.PresubmitPromptOrNotify(error_message, problems)]
2293 else:
2294 return []
Mohamed Heikal5e5b7922020-10-29 18:57:592295
2296
Saagar Sanghavifceeaae2020-08-12 16:40:362297def CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502298 """Attempts to prevent use of functions intended only for testing in
2299 non-testing code. For now this is just a best-effort implementation
2300 that ignores header files and may have some false positives. A
2301 better implementation would probably need a proper C++ parser.
2302 """
2303 # We only scan .cc files and the like, as the declaration of
2304 # for-testing functions in header files are hard to distinguish from
2305 # calls to such functions without a proper C++ parser.
2306 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:192307
Sam Maiera6e76d72022-02-11 21:43:502308 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
2309 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' %
2310 base_function_pattern)
2311 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
2312 allowlist_pattern = input_api.re.compile(r'// IN-TEST$')
2313 exclusion_pattern = input_api.re.compile(
2314 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' %
2315 (base_function_pattern, base_function_pattern))
2316 # Avoid a false positive in this case, where the method name, the ::, and
2317 # the closing { are all on different lines due to line wrapping.
2318 # HelperClassForTesting::
2319 # HelperClassForTesting(
2320 # args)
2321 # : member(0) {}
2322 method_defn_pattern = input_api.re.compile(r'[A-Za-z0-9_]+::$')
[email protected]55459852011-08-10 15:17:192323
Sam Maiera6e76d72022-02-11 21:43:502324 def FilterFile(affected_file):
2325 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2326 input_api.DEFAULT_FILES_TO_SKIP)
2327 return input_api.FilterSourceFile(
2328 affected_file,
2329 files_to_check=file_inclusion_pattern,
2330 files_to_skip=files_to_skip)
[email protected]55459852011-08-10 15:17:192331
Sam Maiera6e76d72022-02-11 21:43:502332 problems = []
2333 for f in input_api.AffectedSourceFiles(FilterFile):
2334 local_path = f.LocalPath()
2335 in_method_defn = False
2336 for line_number, line in f.ChangedContents():
2337 if (inclusion_pattern.search(line)
2338 and not comment_pattern.search(line)
2339 and not exclusion_pattern.search(line)
2340 and not allowlist_pattern.search(line)
2341 and not in_method_defn):
2342 problems.append('%s:%d\n %s' %
2343 (local_path, line_number, line.strip()))
2344 in_method_defn = method_defn_pattern.search(line)
[email protected]55459852011-08-10 15:17:192345
Sam Maiera6e76d72022-02-11 21:43:502346 if problems:
2347 return [
2348 output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)
2349 ]
2350 else:
2351 return []
[email protected]55459852011-08-10 15:17:192352
2353
Saagar Sanghavifceeaae2020-08-12 16:40:362354def CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502355 """This is a simplified version of
2356 CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
2357 """
2358 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
2359 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
2360 name_pattern = r'ForTest(s|ing)?'
2361 # Describes an occurrence of "ForTest*" inside a // comment.
2362 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
2363 # Describes @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
2364 annotation_re = input_api.re.compile(r'@VisibleForTesting\(')
2365 # Catch calls.
2366 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
2367 # Ignore definitions. (Comments are ignored separately.)
2368 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
Andrew Grieve40f451d2023-07-06 19:46:512369 allowlist_re = input_api.re.compile(r'// IN-TEST$')
Vaclav Brozek7dbc28c2018-03-27 08:35:232370
Sam Maiera6e76d72022-02-11 21:43:502371 problems = []
2372 sources = lambda x: input_api.FilterSourceFile(
2373 x,
2374 files_to_skip=(('(?i).*test', r'.*\/junit\/') + input_api.
2375 DEFAULT_FILES_TO_SKIP),
2376 files_to_check=[r'.*\.java$'])
2377 for f in input_api.AffectedFiles(include_deletes=False,
2378 file_filter=sources):
2379 local_path = f.LocalPath()
Vaclav Brozek7dbc28c2018-03-27 08:35:232380 is_inside_javadoc = False
Sam Maiera6e76d72022-02-11 21:43:502381 for line_number, line in f.ChangedContents():
2382 if is_inside_javadoc and javadoc_end_re.search(line):
2383 is_inside_javadoc = False
2384 if not is_inside_javadoc and javadoc_start_re.search(line):
2385 is_inside_javadoc = True
2386 if is_inside_javadoc:
2387 continue
2388 if (inclusion_re.search(line) and not comment_re.search(line)
2389 and not annotation_re.search(line)
Andrew Grieve40f451d2023-07-06 19:46:512390 and not allowlist_re.search(line)
Sam Maiera6e76d72022-02-11 21:43:502391 and not exclusion_re.search(line)):
2392 problems.append('%s:%d\n %s' %
2393 (local_path, line_number, line.strip()))
Vaclav Brozek7dbc28c2018-03-27 08:35:232394
Sam Maiera6e76d72022-02-11 21:43:502395 if problems:
2396 return [
2397 output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)
2398 ]
2399 else:
2400 return []
Vaclav Brozek7dbc28c2018-03-27 08:35:232401
2402
Saagar Sanghavifceeaae2020-08-12 16:40:362403def CheckNoIOStreamInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502404 """Checks to make sure no .h files include <iostream>."""
2405 files = []
2406 pattern = input_api.re.compile(r'^#include\s*<iostream>',
2407 input_api.re.MULTILINE)
2408 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2409 if not f.LocalPath().endswith('.h'):
2410 continue
2411 contents = input_api.ReadFile(f)
2412 if pattern.search(contents):
2413 files.append(f)
[email protected]10689ca2011-09-02 02:31:542414
Sam Maiera6e76d72022-02-11 21:43:502415 if len(files):
2416 return [
2417 output_api.PresubmitError(
2418 'Do not #include <iostream> in header files, since it inserts static '
2419 'initialization into every file including the header. Instead, '
2420 '#include <ostream>. See http://crbug.com/94794', files)
2421 ]
2422 return []
2423
[email protected]10689ca2011-09-02 02:31:542424
Aleksey Khoroshilov9b28c032022-06-03 16:35:322425def CheckNoStrCatRedefines(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502426 """Checks no windows headers with StrCat redefined are included directly."""
2427 files = []
Aleksey Khoroshilov9b28c032022-06-03 16:35:322428 files_to_check = (r'.+%s' % _HEADER_EXTENSIONS,
2429 r'.+%s' % _IMPLEMENTATION_EXTENSIONS)
2430 files_to_skip = (input_api.DEFAULT_FILES_TO_SKIP +
2431 _NON_BASE_DEPENDENT_PATHS)
2432 sources_filter = lambda f: input_api.FilterSourceFile(
2433 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
2434
Sam Maiera6e76d72022-02-11 21:43:502435 pattern_deny = input_api.re.compile(
2436 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
2437 input_api.re.MULTILINE)
2438 pattern_allow = input_api.re.compile(
2439 r'^#include\s"base/win/windows_defines.inc"', input_api.re.MULTILINE)
Aleksey Khoroshilov9b28c032022-06-03 16:35:322440 for f in input_api.AffectedSourceFiles(sources_filter):
Sam Maiera6e76d72022-02-11 21:43:502441 contents = input_api.ReadFile(f)
2442 if pattern_deny.search(
2443 contents) and not pattern_allow.search(contents):
2444 files.append(f.LocalPath())
Danil Chapovalov3518f362018-08-11 16:13:432445
Sam Maiera6e76d72022-02-11 21:43:502446 if len(files):
2447 return [
2448 output_api.PresubmitError(
2449 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
2450 'directly since they pollute code with StrCat macro. Instead, '
2451 'include matching header from base/win. See http://crbug.com/856536',
2452 files)
2453 ]
2454 return []
Danil Chapovalov3518f362018-08-11 16:13:432455
[email protected]10689ca2011-09-02 02:31:542456
Andrew Williamsc9f69b482023-07-10 16:07:362457def _CheckNoUNIT_TESTInSourceFiles(input_api, f):
2458 problems = []
2459
2460 unit_test_macro = input_api.re.compile(
2461 '^\s*#.*(?:ifn?def\s+UNIT_TEST|defined\s*\(?\s*UNIT_TEST\s*\)?)(?:$|\s+)')
2462 for line_num, line in f.ChangedContents():
2463 if unit_test_macro.match(line):
2464 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2465
2466 return problems
2467
2468
Saagar Sanghavifceeaae2020-08-12 16:40:362469def CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502470 """Checks to make sure no source files use UNIT_TEST."""
2471 problems = []
2472 for f in input_api.AffectedFiles():
2473 if (not f.LocalPath().endswith(('.cc', '.mm'))):
2474 continue
Andrew Williamsc9f69b482023-07-10 16:07:362475 problems.extend(
2476 _CheckNoUNIT_TESTInSourceFiles(input_api, f))
[email protected]72df4e782012-06-21 16:28:182477
Sam Maiera6e76d72022-02-11 21:43:502478 if not problems:
2479 return []
2480 return [
2481 output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
2482 '\n'.join(problems))
2483 ]
2484
[email protected]72df4e782012-06-21 16:28:182485
Saagar Sanghavifceeaae2020-08-12 16:40:362486def CheckNoDISABLETypoInTests(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502487 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
Dominic Battre033531052018-09-24 15:45:342488
Sam Maiera6e76d72022-02-11 21:43:502489 This test warns if somebody tries to disable a test with the DISABLE_ prefix
2490 instead of DISABLED_. To filter false positives, reports are only generated
2491 if a corresponding MAYBE_ line exists.
2492 """
2493 problems = []
Dominic Battre033531052018-09-24 15:45:342494
Sam Maiera6e76d72022-02-11 21:43:502495 # The following two patterns are looked for in tandem - is a test labeled
2496 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
2497 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
2498 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
Dominic Battre033531052018-09-24 15:45:342499
Sam Maiera6e76d72022-02-11 21:43:502500 # This is for the case that a test is disabled on all platforms.
2501 full_disable_pattern = input_api.re.compile(
2502 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
2503 input_api.re.MULTILINE)
Dominic Battre033531052018-09-24 15:45:342504
Arthur Sonzognic66e9c82024-04-23 07:53:042505 for f in input_api.AffectedFiles(include_deletes=False):
Sam Maiera6e76d72022-02-11 21:43:502506 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
2507 continue
Dominic Battre033531052018-09-24 15:45:342508
Arthur Sonzognic66e9c82024-04-23 07:53:042509 # Search for MAYBE_, DISABLE_ pairs.
Sam Maiera6e76d72022-02-11 21:43:502510 disable_lines = {} # Maps of test name to line number.
2511 maybe_lines = {}
2512 for line_num, line in f.ChangedContents():
2513 disable_match = disable_pattern.search(line)
2514 if disable_match:
2515 disable_lines[disable_match.group(1)] = line_num
2516 maybe_match = maybe_pattern.search(line)
2517 if maybe_match:
2518 maybe_lines[maybe_match.group(1)] = line_num
Dominic Battre033531052018-09-24 15:45:342519
Sam Maiera6e76d72022-02-11 21:43:502520 # Search for DISABLE_ occurrences within a TEST() macro.
2521 disable_tests = set(disable_lines.keys())
2522 maybe_tests = set(maybe_lines.keys())
2523 for test in disable_tests.intersection(maybe_tests):
2524 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
Dominic Battre033531052018-09-24 15:45:342525
Sam Maiera6e76d72022-02-11 21:43:502526 contents = input_api.ReadFile(f)
2527 full_disable_match = full_disable_pattern.search(contents)
2528 if full_disable_match:
2529 problems.append(' %s' % f.LocalPath())
Dominic Battre033531052018-09-24 15:45:342530
Sam Maiera6e76d72022-02-11 21:43:502531 if not problems:
2532 return []
2533 return [
2534 output_api.PresubmitPromptWarning(
2535 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
2536 '\n'.join(problems))
2537 ]
2538
Dominic Battre033531052018-09-24 15:45:342539
Nina Satragnof7660532021-09-20 18:03:352540def CheckForgettingMAYBEInTests(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502541 """Checks to make sure tests disabled conditionally are not missing a
2542 corresponding MAYBE_ prefix.
2543 """
2544 # Expect at least a lowercase character in the test name. This helps rule out
2545 # false positives with macros wrapping the actual tests name.
2546 define_maybe_pattern = input_api.re.compile(
2547 r'^\#define MAYBE_(?P<test_name>\w*[a-z]\w*)')
Bruce Dawsonffc55292022-04-20 04:18:192548 # The test_maybe_pattern needs to handle all of these forms. The standard:
2549 # IN_PROC_TEST_F(SyncTest, MAYBE_Start) {
2550 # With a wrapper macro around the test name:
2551 # IN_PROC_TEST_F(SyncTest, E2E_ENABLED(MAYBE_Start)) {
2552 # And the odd-ball NACL_BROWSER_TEST_f format:
2553 # NACL_BROWSER_TEST_F(NaClBrowserTest, SimpleLoad, {
2554 # The optional E2E_ENABLED-style is handled with (\w*\()?
2555 # The NACL_BROWSER_TEST_F pattern is handled by allowing a trailing comma or
2556 # trailing ')'.
2557 test_maybe_pattern = (
2558 r'^\s*\w*TEST[^(]*\(\s*\w+,\s*(\w*\()?MAYBE_{test_name}[\),]')
Sam Maiera6e76d72022-02-11 21:43:502559 suite_maybe_pattern = r'^\s*\w*TEST[^(]*\(\s*MAYBE_{test_name}[\),]'
2560 warnings = []
Nina Satragnof7660532021-09-20 18:03:352561
Sam Maiera6e76d72022-02-11 21:43:502562 # Read the entire files. We can't just read the affected lines, forgetting to
2563 # add MAYBE_ on a change would not show up otherwise.
Arthur Sonzognic66e9c82024-04-23 07:53:042564 for f in input_api.AffectedFiles(include_deletes=False):
Sam Maiera6e76d72022-02-11 21:43:502565 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
2566 continue
2567 contents = input_api.ReadFile(f)
2568 lines = contents.splitlines(True)
2569 current_position = 0
2570 warning_test_names = set()
2571 for line_num, line in enumerate(lines, start=1):
2572 current_position += len(line)
2573 maybe_match = define_maybe_pattern.search(line)
2574 if maybe_match:
2575 test_name = maybe_match.group('test_name')
2576 # Do not warn twice for the same test.
2577 if (test_name in warning_test_names):
2578 continue
2579 warning_test_names.add(test_name)
Nina Satragnof7660532021-09-20 18:03:352580
Sam Maiera6e76d72022-02-11 21:43:502581 # Attempt to find the corresponding MAYBE_ test or suite, starting from
2582 # the current position.
2583 test_match = input_api.re.compile(
2584 test_maybe_pattern.format(test_name=test_name),
2585 input_api.re.MULTILINE).search(contents, current_position)
2586 suite_match = input_api.re.compile(
2587 suite_maybe_pattern.format(test_name=test_name),
2588 input_api.re.MULTILINE).search(contents, current_position)
2589 if not test_match and not suite_match:
2590 warnings.append(
2591 output_api.PresubmitPromptWarning(
2592 '%s:%d found MAYBE_ defined without corresponding test %s'
2593 % (f.LocalPath(), line_num, test_name)))
2594 return warnings
2595
[email protected]72df4e782012-06-21 16:28:182596
Saagar Sanghavifceeaae2020-08-12 16:40:362597def CheckDCHECK_IS_ONHasBraces(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502598 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
2599 errors = []
Kalvin Lee4a3b79de2022-05-26 16:00:162600 pattern = input_api.re.compile(r'\bDCHECK_IS_ON\b(?!\(\))',
Sam Maiera6e76d72022-02-11 21:43:502601 input_api.re.MULTILINE)
2602 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2603 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
2604 continue
2605 for lnum, line in f.ChangedContents():
2606 if input_api.re.search(pattern, line):
2607 errors.append(
2608 output_api.PresubmitError((
2609 '%s:%d: Use of DCHECK_IS_ON() must be written as "#if '
2610 + 'DCHECK_IS_ON()", not forgetting the parentheses.') %
2611 (f.LocalPath(), lnum)))
2612 return errors
danakj61c1aa22015-10-26 19:55:522613
2614
Weilun Shia487fad2020-10-28 00:10:342615# TODO(crbug/1138055): Reimplement CheckUmaHistogramChangesOnUpload check in a
2616# more reliable way. See
2617# https://chromium-review.googlesource.com/c/chromium/src/+/2500269
mcasasb7440c282015-02-04 14:52:192618
wnwenbdc444e2016-05-25 13:44:152619
Saagar Sanghavifceeaae2020-08-12 16:40:362620def CheckFlakyTestUsage(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502621 """Check that FlakyTest annotation is our own instead of the android one"""
2622 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
2623 files = []
2624 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2625 if f.LocalPath().endswith('Test.java'):
2626 if pattern.search(input_api.ReadFile(f)):
2627 files.append(f)
2628 if len(files):
2629 return [
2630 output_api.PresubmitError(
2631 'Use org.chromium.base.test.util.FlakyTest instead of '
2632 'android.test.FlakyTest', files)
2633 ]
2634 return []
mcasasb7440c282015-02-04 14:52:192635
wnwenbdc444e2016-05-25 13:44:152636
Saagar Sanghavifceeaae2020-08-12 16:40:362637def CheckNoDEPSGIT(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502638 """Make sure .DEPS.git is never modified manually."""
2639 if any(f.LocalPath().endswith('.DEPS.git')
2640 for f in input_api.AffectedFiles()):
2641 return [
2642 output_api.PresubmitError(
2643 'Never commit changes to .DEPS.git. This file is maintained by an\n'
2644 'automated system based on what\'s in DEPS and your changes will be\n'
2645 'overwritten.\n'
2646 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
2647 'get-the-code#Rolling_DEPS\n'
2648 'for more information')
2649 ]
2650 return []
[email protected]2a8ac9c2011-10-19 17:20:442651
2652
Sven Zheng76a79ea2022-12-21 21:25:242653def CheckCrosApiNeedBrowserTest(input_api, output_api):
2654 """Check new crosapi should add browser test."""
2655 has_new_crosapi = False
2656 has_browser_test = False
2657 for f in input_api.AffectedFiles():
2658 path = f.LocalPath()
2659 if (path.startswith('chromeos/crosapi/mojom') and
2660 _IsMojomFile(input_api, path) and f.Action() == 'A'):
2661 has_new_crosapi = True
2662 if path.endswith('browsertest.cc') or path.endswith('browser_test.cc'):
2663 has_browser_test = True
2664 if has_new_crosapi and not has_browser_test:
2665 return [
2666 output_api.PresubmitPromptWarning(
2667 'You are adding a new crosapi, but there is no file ends with '
2668 'browsertest.cc file being added or modified. It is important '
2669 'to add crosapi browser test coverage to avoid version '
2670 ' skew issues.\n'
2671 'Check //docs/lacros/test_instructions.md for more information.'
2672 )
2673 ]
2674 return []
2675
2676
Saagar Sanghavifceeaae2020-08-12 16:40:362677def CheckValidHostsInDEPSOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502678 """Checks that DEPS file deps are from allowed_hosts."""
2679 # Run only if DEPS file has been modified to annoy fewer bystanders.
2680 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
2681 return []
2682 # Outsource work to gclient verify
2683 try:
2684 gclient_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
2685 'third_party', 'depot_tools',
2686 'gclient.py')
2687 input_api.subprocess.check_output(
Bruce Dawson8a43cf72022-05-13 17:10:322688 [input_api.python3_executable, gclient_path, 'verify'],
Sam Maiera6e76d72022-02-11 21:43:502689 stderr=input_api.subprocess.STDOUT)
2690 return []
2691 except input_api.subprocess.CalledProcessError as error:
2692 return [
2693 output_api.PresubmitError(
2694 'DEPS file must have only git dependencies.',
2695 long_text=error.output)
2696 ]
tandriief664692014-09-23 14:51:472697
2698
Mario Sanchez Prada2472cab2019-09-18 10:58:312699def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
Daniel Chenga44a1bcd2022-03-15 20:00:152700 ban_rule):
Allen Bauer84778682022-09-22 16:28:562701 """Helper method for checking for banned constructs.
Mario Sanchez Prada2472cab2019-09-18 10:58:312702
Sam Maiera6e76d72022-02-11 21:43:502703 Returns an string composed of the name of the file, the line number where the
2704 match has been found and the additional text passed as |message| in case the
2705 target type name matches the text inside the line passed as parameter.
2706 """
2707 result = []
Peng Huang9c5949a02020-06-11 19:20:542708
Daniel Chenga44a1bcd2022-03-15 20:00:152709 # Ignore comments about banned types.
2710 if input_api.re.search(r"^ *//", line):
Sam Maiera6e76d72022-02-11 21:43:502711 return result
Daniel Chenga44a1bcd2022-03-15 20:00:152712 # A // nocheck comment will bypass this error.
2713 if line.endswith(" nocheck"):
Sam Maiera6e76d72022-02-11 21:43:502714 return result
2715
2716 matched = False
Daniel Chenga44a1bcd2022-03-15 20:00:152717 if ban_rule.pattern[0:1] == '/':
2718 regex = ban_rule.pattern[1:]
Sam Maiera6e76d72022-02-11 21:43:502719 if input_api.re.search(regex, line):
2720 matched = True
Daniel Chenga44a1bcd2022-03-15 20:00:152721 elif ban_rule.pattern in line:
Sam Maiera6e76d72022-02-11 21:43:502722 matched = True
2723
2724 if matched:
2725 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
Daniel Chenga44a1bcd2022-03-15 20:00:152726 for line in ban_rule.explanation:
2727 result.append(' %s' % line)
Sam Maiera6e76d72022-02-11 21:43:502728
danakjd18e8892020-12-17 17:42:012729 return result
Mario Sanchez Prada2472cab2019-09-18 10:58:312730
2731
Saagar Sanghavifceeaae2020-08-12 16:40:362732def CheckNoBannedFunctions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502733 """Make sure that banned functions are not used."""
2734 warnings = []
2735 errors = []
[email protected]127f18ec2012-06-16 05:05:592736
Sam Maiera6e76d72022-02-11 21:43:502737 def IsExcludedFile(affected_file, excluded_paths):
Daniel Chenga44a1bcd2022-03-15 20:00:152738 if not excluded_paths:
2739 return False
2740
Sam Maiera6e76d72022-02-11 21:43:502741 local_path = affected_file.LocalPath()
Bruce Dawson40fece62022-09-16 19:58:312742 # Consistently use / as path separator to simplify the writing of regex
2743 # expressions.
2744 local_path = local_path.replace(input_api.os_path.sep, '/')
Sam Maiera6e76d72022-02-11 21:43:502745 for item in excluded_paths:
2746 if input_api.re.match(item, local_path):
2747 return True
2748 return False
wnwenbdc444e2016-05-25 13:44:152749
Sam Maiera6e76d72022-02-11 21:43:502750 def IsIosObjcFile(affected_file):
2751 local_path = affected_file.LocalPath()
2752 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m',
2753 '.h'):
2754 return False
2755 basename = input_api.os_path.basename(local_path)
2756 if 'ios' in basename.split('_'):
2757 return True
2758 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
2759 if sep and 'ios' in local_path.split(sep):
2760 return True
2761 return False
Sylvain Defresnea8b73d252018-02-28 15:45:542762
Daniel Chenga44a1bcd2022-03-15 20:00:152763 def CheckForMatch(affected_file, line_num: int, line: str,
2764 ban_rule: BanRule):
2765 if IsExcludedFile(affected_file, ban_rule.excluded_paths):
2766 return
2767
Sam Maiera6e76d72022-02-11 21:43:502768 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
Daniel Chenga44a1bcd2022-03-15 20:00:152769 ban_rule)
Sam Maiera6e76d72022-02-11 21:43:502770 if problems:
Daniel Chenga44a1bcd2022-03-15 20:00:152771 if ban_rule.treat_as_error is not None and ban_rule.treat_as_error:
Sam Maiera6e76d72022-02-11 21:43:502772 errors.extend(problems)
2773 else:
2774 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:152775
Sam Maiera6e76d72022-02-11 21:43:502776 file_filter = lambda f: f.LocalPath().endswith(('.java'))
2777 for f in input_api.AffectedFiles(file_filter=file_filter):
2778 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152779 for ban_rule in _BANNED_JAVA_FUNCTIONS:
2780 CheckForMatch(f, line_num, line, ban_rule)
Eric Stevensona9a980972017-09-23 00:04:412781
Clement Yan9b330cb2022-11-17 05:25:292782 file_filter = lambda f: f.LocalPath().endswith(('.js', '.ts'))
2783 for f in input_api.AffectedFiles(file_filter=file_filter):
2784 for line_num, line in f.ChangedContents():
2785 for ban_rule in _BANNED_JAVASCRIPT_FUNCTIONS:
2786 CheckForMatch(f, line_num, line, ban_rule)
2787
Sam Maiera6e76d72022-02-11 21:43:502788 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
2789 for f in input_api.AffectedFiles(file_filter=file_filter):
2790 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152791 for ban_rule in _BANNED_OBJC_FUNCTIONS:
2792 CheckForMatch(f, line_num, line, ban_rule)
[email protected]127f18ec2012-06-16 05:05:592793
Sam Maiera6e76d72022-02-11 21:43:502794 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
2795 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152796 for ban_rule in _BANNED_IOS_OBJC_FUNCTIONS:
2797 CheckForMatch(f, line_num, line, ban_rule)
Sylvain Defresnea8b73d252018-02-28 15:45:542798
Sam Maiera6e76d72022-02-11 21:43:502799 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
2800 for f in input_api.AffectedFiles(file_filter=egtest_filter):
2801 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152802 for ban_rule in _BANNED_IOS_EGTEST_FUNCTIONS:
2803 CheckForMatch(f, line_num, line, ban_rule)
Peter K. Lee6c03ccff2019-07-15 14:40:052804
Sam Maiera6e76d72022-02-11 21:43:502805 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
2806 for f in input_api.AffectedFiles(file_filter=file_filter):
2807 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152808 for ban_rule in _BANNED_CPP_FUNCTIONS:
2809 CheckForMatch(f, line_num, line, ban_rule)
[email protected]127f18ec2012-06-16 05:05:592810
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:152811 # As of 05/2024, iOS fully migrated ConsentLevel::kSync to kSignin, and
2812 # Android is in the process of preventing new users from entering kSync.
2813 # So the warning is restricted to those platforms.
2814 ios_pattern = input_api.re.compile('(^|[\W_])ios[\W_]')
2815 file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.mm', '.h')) and
2816 ('android' in f.LocalPath() or
2817 # Simply checking for an 'ios' substring would
2818 # catch unrelated cases, use a regex.
2819 ios_pattern.search(f.LocalPath())))
2820 for f in input_api.AffectedFiles(file_filter=file_filter):
2821 for line_num, line in f.ChangedContents():
2822 for ban_rule in _DEPRECATED_SYNC_CONSENT_CPP_FUNCTIONS:
2823 CheckForMatch(f, line_num, line, ban_rule)
2824
2825 file_filter = lambda f: f.LocalPath().endswith(('.java'))
2826 for f in input_api.AffectedFiles(file_filter=file_filter):
2827 for line_num, line in f.ChangedContents():
2828 for ban_rule in _DEPRECATED_SYNC_CONSENT_JAVA_FUNCTIONS:
2829 CheckForMatch(f, line_num, line, ban_rule)
2830
Daniel Cheng92c15e32022-03-16 17:48:222831 file_filter = lambda f: f.LocalPath().endswith(('.mojom'))
2832 for f in input_api.AffectedFiles(file_filter=file_filter):
2833 for line_num, line in f.ChangedContents():
2834 for ban_rule in _BANNED_MOJOM_PATTERNS:
2835 CheckForMatch(f, line_num, line, ban_rule)
2836
2837
Sam Maiera6e76d72022-02-11 21:43:502838 result = []
2839 if (warnings):
2840 result.append(
2841 output_api.PresubmitPromptWarning('Banned functions were used.\n' +
2842 '\n'.join(warnings)))
2843 if (errors):
2844 result.append(
2845 output_api.PresubmitError('Banned functions were used.\n' +
2846 '\n'.join(errors)))
2847 return result
[email protected]127f18ec2012-06-16 05:05:592848
Michael Thiessen44457642020-02-06 00:24:152849def _CheckAndroidNoBannedImports(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502850 """Make sure that banned java imports are not used."""
2851 errors = []
Michael Thiessen44457642020-02-06 00:24:152852
Sam Maiera6e76d72022-02-11 21:43:502853 file_filter = lambda f: f.LocalPath().endswith(('.java'))
2854 for f in input_api.AffectedFiles(file_filter=file_filter):
2855 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152856 for ban_rule in _BANNED_JAVA_IMPORTS:
2857 # Consider merging this into the above function. There is no
2858 # real difference anymore other than helping with a little
2859 # bit of boilerplate text. Doing so means things like
2860 # `treat_as_error` will also be uniformly handled.
Sam Maiera6e76d72022-02-11 21:43:502861 problems = _GetMessageForMatchingType(input_api, f, line_num,
Daniel Chenga44a1bcd2022-03-15 20:00:152862 line, ban_rule)
Sam Maiera6e76d72022-02-11 21:43:502863 if problems:
2864 errors.extend(problems)
2865 result = []
2866 if (errors):
2867 result.append(
2868 output_api.PresubmitError('Banned imports were used.\n' +
2869 '\n'.join(errors)))
2870 return result
Michael Thiessen44457642020-02-06 00:24:152871
2872
Saagar Sanghavifceeaae2020-08-12 16:40:362873def CheckNoPragmaOnce(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502874 """Make sure that banned functions are not used."""
2875 files = []
2876 pattern = input_api.re.compile(r'^#pragma\s+once', input_api.re.MULTILINE)
2877 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2878 if not f.LocalPath().endswith('.h'):
2879 continue
Bruce Dawson4c4c2922022-05-02 18:07:332880 if f.LocalPath().endswith('com_imported_mstscax.h'):
2881 continue
Sam Maiera6e76d72022-02-11 21:43:502882 contents = input_api.ReadFile(f)
2883 if pattern.search(contents):
2884 files.append(f)
[email protected]6c063c62012-07-11 19:11:062885
Sam Maiera6e76d72022-02-11 21:43:502886 if files:
2887 return [
2888 output_api.PresubmitError(
2889 'Do not use #pragma once in header files.\n'
2890 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
2891 files)
2892 ]
2893 return []
[email protected]6c063c62012-07-11 19:11:062894
[email protected]127f18ec2012-06-16 05:05:592895
Saagar Sanghavifceeaae2020-08-12 16:40:362896def CheckNoTrinaryTrueFalse(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502897 """Checks to make sure we don't introduce use of foo ? true : false."""
2898 problems = []
2899 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2900 for f in input_api.AffectedFiles():
2901 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2902 continue
[email protected]e7479052012-09-19 00:26:122903
Sam Maiera6e76d72022-02-11 21:43:502904 for line_num, line in f.ChangedContents():
2905 if pattern.match(line):
2906 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]e7479052012-09-19 00:26:122907
Sam Maiera6e76d72022-02-11 21:43:502908 if not problems:
2909 return []
2910 return [
2911 output_api.PresubmitPromptWarning(
2912 'Please consider avoiding the "? true : false" pattern if possible.\n'
2913 + '\n'.join(problems))
2914 ]
[email protected]e7479052012-09-19 00:26:122915
2916
Saagar Sanghavifceeaae2020-08-12 16:40:362917def CheckUnwantedDependencies(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502918 """Runs checkdeps on #include and import statements added in this
2919 change. Breaking - rules is an error, breaking ! rules is a
2920 warning.
2921 """
2922 # Return early if no relevant file types were modified.
2923 for f in input_api.AffectedFiles():
2924 path = f.LocalPath()
2925 if (_IsCPlusPlusFile(input_api, path) or _IsProtoFile(input_api, path)
2926 or _IsJavaFile(input_api, path)):
2927 break
[email protected]55f9f382012-07-31 11:02:182928 else:
Sam Maiera6e76d72022-02-11 21:43:502929 return []
rhalavati08acd232017-04-03 07:23:282930
Sam Maiera6e76d72022-02-11 21:43:502931 import sys
2932 # We need to wait until we have an input_api object and use this
2933 # roundabout construct to import checkdeps because this file is
2934 # eval-ed and thus doesn't have __file__.
2935 original_sys_path = sys.path
2936 try:
2937 sys.path = sys.path + [
2938 input_api.os_path.join(input_api.PresubmitLocalPath(),
2939 'buildtools', 'checkdeps')
2940 ]
2941 import checkdeps
2942 from rules import Rule
2943 finally:
2944 # Restore sys.path to what it was before.
2945 sys.path = original_sys_path
[email protected]55f9f382012-07-31 11:02:182946
Sam Maiera6e76d72022-02-11 21:43:502947 added_includes = []
2948 added_imports = []
2949 added_java_imports = []
2950 for f in input_api.AffectedFiles():
2951 if _IsCPlusPlusFile(input_api, f.LocalPath()):
2952 changed_lines = [line for _, line in f.ChangedContents()]
2953 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
2954 elif _IsProtoFile(input_api, f.LocalPath()):
2955 changed_lines = [line for _, line in f.ChangedContents()]
2956 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
2957 elif _IsJavaFile(input_api, f.LocalPath()):
2958 changed_lines = [line for _, line in f.ChangedContents()]
2959 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:242960
Sam Maiera6e76d72022-02-11 21:43:502961 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
2962
2963 error_descriptions = []
2964 warning_descriptions = []
2965 error_subjects = set()
2966 warning_subjects = set()
2967
2968 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2969 added_includes):
2970 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
2971 description_with_path = '%s\n %s' % (path, rule_description)
2972 if rule_type == Rule.DISALLOW:
2973 error_descriptions.append(description_with_path)
2974 error_subjects.add("#includes")
2975 else:
2976 warning_descriptions.append(description_with_path)
2977 warning_subjects.add("#includes")
2978
2979 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2980 added_imports):
2981 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
2982 description_with_path = '%s\n %s' % (path, rule_description)
2983 if rule_type == Rule.DISALLOW:
2984 error_descriptions.append(description_with_path)
2985 error_subjects.add("imports")
2986 else:
2987 warning_descriptions.append(description_with_path)
2988 warning_subjects.add("imports")
2989
2990 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
2991 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
2992 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
2993 description_with_path = '%s\n %s' % (path, rule_description)
2994 if rule_type == Rule.DISALLOW:
2995 error_descriptions.append(description_with_path)
2996 error_subjects.add("imports")
2997 else:
2998 warning_descriptions.append(description_with_path)
2999 warning_subjects.add("imports")
3000
3001 results = []
3002 if error_descriptions:
3003 results.append(
3004 output_api.PresubmitError(
3005 'You added one or more %s that violate checkdeps rules.' %
3006 " and ".join(error_subjects), error_descriptions))
3007 if warning_descriptions:
3008 results.append(
3009 output_api.PresubmitPromptOrNotify(
3010 'You added one or more %s of files that are temporarily\n'
3011 'allowed but being removed. Can you avoid introducing the\n'
3012 '%s? See relevant DEPS file(s) for details and contacts.' %
3013 (" and ".join(warning_subjects), "/".join(warning_subjects)),
3014 warning_descriptions))
3015 return results
[email protected]55f9f382012-07-31 11:02:183016
3017
Saagar Sanghavifceeaae2020-08-12 16:40:363018def CheckFilePermissions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503019 """Check that all files have their permissions properly set."""
3020 if input_api.platform == 'win32':
3021 return []
3022 checkperms_tool = input_api.os_path.join(input_api.PresubmitLocalPath(),
3023 'tools', 'checkperms',
3024 'checkperms.py')
3025 args = [
Bruce Dawson8a43cf72022-05-13 17:10:323026 input_api.python3_executable, checkperms_tool, '--root',
Sam Maiera6e76d72022-02-11 21:43:503027 input_api.change.RepositoryRoot()
3028 ]
3029 with input_api.CreateTemporaryFile() as file_list:
3030 for f in input_api.AffectedFiles():
3031 # checkperms.py file/directory arguments must be relative to the
3032 # repository.
3033 file_list.write((f.LocalPath() + '\n').encode('utf8'))
3034 file_list.close()
3035 args += ['--file-list', file_list.name]
3036 try:
3037 input_api.subprocess.check_output(args)
3038 return []
3039 except input_api.subprocess.CalledProcessError as error:
3040 return [
3041 output_api.PresubmitError('checkperms.py failed:',
3042 long_text=error.output.decode(
3043 'utf-8', 'ignore'))
3044 ]
[email protected]fbcafe5a2012-08-08 15:31:223045
3046
Saagar Sanghavifceeaae2020-08-12 16:40:363047def CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503048 """Makes sure we don't include ui/aura/window_property.h
3049 in header files.
3050 """
3051 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
3052 errors = []
3053 for f in input_api.AffectedFiles():
3054 if not f.LocalPath().endswith('.h'):
3055 continue
3056 for line_num, line in f.ChangedContents():
3057 if pattern.match(line):
3058 errors.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]c8278b32012-10-30 20:35:493059
Sam Maiera6e76d72022-02-11 21:43:503060 results = []
3061 if errors:
3062 results.append(
3063 output_api.PresubmitError(
3064 'Header files should not include ui/aura/window_property.h',
3065 errors))
3066 return results
[email protected]c8278b32012-10-30 20:35:493067
3068
Omer Katzcc77ea92021-04-26 10:23:283069def CheckNoInternalHeapIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503070 """Makes sure we don't include any headers from
3071 third_party/blink/renderer/platform/heap/impl or
3072 third_party/blink/renderer/platform/heap/v8_wrapper from files outside of
3073 third_party/blink/renderer/platform/heap
3074 """
3075 impl_pattern = input_api.re.compile(
3076 r'^\s*#include\s*"third_party/blink/renderer/platform/heap/impl/.*"')
3077 v8_wrapper_pattern = input_api.re.compile(
3078 r'^\s*#include\s*"third_party/blink/renderer/platform/heap/v8_wrapper/.*"'
3079 )
Bruce Dawson40fece62022-09-16 19:58:313080 # Consistently use / as path separator to simplify the writing of regex
3081 # expressions.
Sam Maiera6e76d72022-02-11 21:43:503082 file_filter = lambda f: not input_api.re.match(
Bruce Dawson40fece62022-09-16 19:58:313083 r"^third_party/blink/renderer/platform/heap/.*",
3084 f.LocalPath().replace(input_api.os_path.sep, '/'))
Sam Maiera6e76d72022-02-11 21:43:503085 errors = []
Omer Katzcc77ea92021-04-26 10:23:283086
Sam Maiera6e76d72022-02-11 21:43:503087 for f in input_api.AffectedFiles(file_filter=file_filter):
3088 for line_num, line in f.ChangedContents():
3089 if impl_pattern.match(line) or v8_wrapper_pattern.match(line):
3090 errors.append(' %s:%d' % (f.LocalPath(), line_num))
Omer Katzcc77ea92021-04-26 10:23:283091
Sam Maiera6e76d72022-02-11 21:43:503092 results = []
3093 if errors:
3094 results.append(
3095 output_api.PresubmitError(
3096 'Do not include files from third_party/blink/renderer/platform/heap/impl'
3097 ' or third_party/blink/renderer/platform/heap/v8_wrapper. Use the '
3098 'relevant counterparts from third_party/blink/renderer/platform/heap',
3099 errors))
3100 return results
Omer Katzcc77ea92021-04-26 10:23:283101
3102
[email protected]70ca77752012-11-20 03:45:033103def _CheckForVersionControlConflictsInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:503104 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
3105 errors = []
3106 for line_num, line in f.ChangedContents():
3107 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
3108 # First-level headers in markdown look a lot like version control
3109 # conflict markers. http://daringfireball.net/projects/markdown/basics
3110 continue
3111 if pattern.match(line):
3112 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
3113 return errors
[email protected]70ca77752012-11-20 03:45:033114
3115
Saagar Sanghavifceeaae2020-08-12 16:40:363116def CheckForVersionControlConflicts(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503117 """Usually this is not intentional and will cause a compile failure."""
3118 errors = []
3119 for f in input_api.AffectedFiles():
3120 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
[email protected]70ca77752012-11-20 03:45:033121
Sam Maiera6e76d72022-02-11 21:43:503122 results = []
3123 if errors:
3124 results.append(
3125 output_api.PresubmitError(
3126 'Version control conflict markers found, please resolve.',
3127 errors))
3128 return results
[email protected]70ca77752012-11-20 03:45:033129
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203130
Saagar Sanghavifceeaae2020-08-12 16:40:363131def CheckGoogleSupportAnswerUrlOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503132 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
3133 errors = []
3134 for f in input_api.AffectedFiles():
3135 for line_num, line in f.ChangedContents():
3136 if pattern.search(line):
3137 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
estadee17314a02017-01-12 16:22:163138
Sam Maiera6e76d72022-02-11 21:43:503139 results = []
3140 if errors:
3141 results.append(
3142 output_api.PresubmitPromptWarning(
3143 'Found Google support URL addressed by answer number. Please replace '
3144 'with a p= identifier instead. See crbug.com/679462\n',
3145 errors))
3146 return results
estadee17314a02017-01-12 16:22:163147
[email protected]70ca77752012-11-20 03:45:033148
Saagar Sanghavifceeaae2020-08-12 16:40:363149def CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503150 def FilterFile(affected_file):
3151 """Filter function for use with input_api.AffectedSourceFiles,
3152 below. This filters out everything except non-test files from
3153 top-level directories that generally speaking should not hard-code
3154 service URLs (e.g. src/android_webview/, src/content/ and others).
3155 """
3156 return input_api.FilterSourceFile(
3157 affected_file,
Bruce Dawson40fece62022-09-16 19:58:313158 files_to_check=[r'^(android_webview|base|content|net)/.*'],
Sam Maiera6e76d72022-02-11 21:43:503159 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
3160 input_api.DEFAULT_FILES_TO_SKIP))
[email protected]06e6d0ff2012-12-11 01:36:443161
Sam Maiera6e76d72022-02-11 21:43:503162 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
3163 '\.(com|net)[^"]*"')
3164 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
3165 pattern = input_api.re.compile(base_pattern)
3166 problems = [] # items are (filename, line_number, line)
3167 for f in input_api.AffectedSourceFiles(FilterFile):
3168 for line_num, line in f.ChangedContents():
3169 if not comment_pattern.search(line) and pattern.search(line):
3170 problems.append((f.LocalPath(), line_num, line))
[email protected]06e6d0ff2012-12-11 01:36:443171
Sam Maiera6e76d72022-02-11 21:43:503172 if problems:
3173 return [
3174 output_api.PresubmitPromptOrNotify(
3175 'Most layers below src/chrome/ should not hardcode service URLs.\n'
3176 'Are you sure this is correct?', [
3177 ' %s:%d: %s' % (problem[0], problem[1], problem[2])
3178 for problem in problems
3179 ])
3180 ]
3181 else:
3182 return []
[email protected]06e6d0ff2012-12-11 01:36:443183
3184
Saagar Sanghavifceeaae2020-08-12 16:40:363185def CheckChromeOsSyncedPrefRegistration(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503186 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
James Cook6b6597c2019-11-06 22:05:293187
Sam Maiera6e76d72022-02-11 21:43:503188 def FileFilter(affected_file):
3189 """Includes directories known to be Chrome OS only."""
3190 return input_api.FilterSourceFile(
3191 affected_file,
3192 files_to_check=(
3193 '^ash/',
3194 '^chromeos/', # Top-level src/chromeos.
3195 '.*/chromeos/', # Any path component.
3196 '^components/arc',
3197 '^components/exo'),
3198 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP))
James Cook6b6597c2019-11-06 22:05:293199
Sam Maiera6e76d72022-02-11 21:43:503200 prefs = []
3201 priority_prefs = []
3202 for f in input_api.AffectedFiles(file_filter=FileFilter):
3203 for line_num, line in f.ChangedContents():
3204 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF',
3205 line):
3206 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
3207 prefs.append(' %s' % line)
3208 if input_api.re.search(
3209 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
3210 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
3211 priority_prefs.append(' %s' % line)
3212
3213 results = []
3214 if (prefs):
3215 results.append(
3216 output_api.PresubmitPromptWarning(
3217 'Preferences were registered as SYNCABLE_PREF and will be controlled '
3218 'by browser sync settings. If these prefs should be controlled by OS '
3219 'sync settings use SYNCABLE_OS_PREF instead.\n' +
3220 '\n'.join(prefs)))
3221 if (priority_prefs):
3222 results.append(
3223 output_api.PresubmitPromptWarning(
3224 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
3225 'controlled by browser sync settings. If these prefs should be '
3226 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
3227 'instead.\n' + '\n'.join(prefs)))
3228 return results
James Cook6b6597c2019-11-06 22:05:293229
3230
Saagar Sanghavifceeaae2020-08-12 16:40:363231def CheckNoAbbreviationInPngFileName(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503232 """Makes sure there are no abbreviations in the name of PNG files.
3233 The native_client_sdk directory is excluded because it has auto-generated PNG
3234 files for documentation.
3235 """
3236 errors = []
Yuanqing Zhu9eef02832022-12-04 14:42:173237 files_to_check = [r'.*\.png$']
Bruce Dawson40fece62022-09-16 19:58:313238 files_to_skip = [r'^native_client_sdk/',
3239 r'^services/test/',
3240 r'^third_party/blink/web_tests/',
Bruce Dawson3db456212022-05-02 05:34:183241 ]
Sam Maiera6e76d72022-02-11 21:43:503242 file_filter = lambda f: input_api.FilterSourceFile(
3243 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
Yuanqing Zhu9eef02832022-12-04 14:42:173244 abbreviation = input_api.re.compile('.+_[a-z]\.png|.+_[a-z]_.*\.png')
Sam Maiera6e76d72022-02-11 21:43:503245 for f in input_api.AffectedFiles(include_deletes=False,
3246 file_filter=file_filter):
Yuanqing Zhu9eef02832022-12-04 14:42:173247 file_name = input_api.os_path.split(f.LocalPath())[1]
3248 if abbreviation.search(file_name):
3249 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:273250
Sam Maiera6e76d72022-02-11 21:43:503251 results = []
3252 if errors:
3253 results.append(
3254 output_api.PresubmitError(
3255 'The name of PNG files should not have abbreviations. \n'
3256 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
3257 'Contact [email protected] if you have questions.', errors))
3258 return results
[email protected]d2530012013-01-25 16:39:273259
Evan Stade7cd4a2c2022-08-04 23:37:253260def CheckNoProductIconsAddedToPublicRepo(input_api, output_api):
3261 """Heuristically identifies product icons based on their file name and reminds
3262 contributors not to add them to the Chromium repository.
3263 """
3264 errors = []
3265 files_to_check = [r'.*google.*\.png$|.*google.*\.svg$|.*google.*\.icon$']
3266 file_filter = lambda f: input_api.FilterSourceFile(
3267 f, files_to_check=files_to_check)
3268 for f in input_api.AffectedFiles(include_deletes=False,
3269 file_filter=file_filter):
3270 errors.append(' %s' % f.LocalPath())
3271
3272 results = []
3273 if errors:
Bruce Dawson3bcf0c92022-08-12 00:03:083274 # Give warnings instead of errors on presubmit --all and presubmit
3275 # --files.
3276 message_type = (output_api.PresubmitNotifyResult if input_api.no_diffs
3277 else output_api.PresubmitError)
Evan Stade7cd4a2c2022-08-04 23:37:253278 results.append(
Bruce Dawson3bcf0c92022-08-12 00:03:083279 message_type(
Evan Stade7cd4a2c2022-08-04 23:37:253280 'Trademarked images should not be added to the public repo. '
3281 'See crbug.com/944754', errors))
3282 return results
3283
[email protected]d2530012013-01-25 16:39:273284
Daniel Cheng4dcdb6b2017-04-13 08:30:173285def _ExtractAddRulesFromParsedDeps(parsed_deps):
Sam Maiera6e76d72022-02-11 21:43:503286 """Extract the rules that add dependencies from a parsed DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:173287
Sam Maiera6e76d72022-02-11 21:43:503288 Args:
3289 parsed_deps: the locals dictionary from evaluating the DEPS file."""
3290 add_rules = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:173291 add_rules.update([
Sam Maiera6e76d72022-02-11 21:43:503292 rule[1:] for rule in parsed_deps.get('include_rules', [])
Daniel Cheng4dcdb6b2017-04-13 08:30:173293 if rule.startswith('+') or rule.startswith('!')
3294 ])
Sam Maiera6e76d72022-02-11 21:43:503295 for _, rules in parsed_deps.get('specific_include_rules', {}).items():
3296 add_rules.update([
3297 rule[1:] for rule in rules
3298 if rule.startswith('+') or rule.startswith('!')
3299 ])
3300 return add_rules
Daniel Cheng4dcdb6b2017-04-13 08:30:173301
3302
3303def _ParseDeps(contents):
Sam Maiera6e76d72022-02-11 21:43:503304 """Simple helper for parsing DEPS files."""
Daniel Cheng4dcdb6b2017-04-13 08:30:173305
Sam Maiera6e76d72022-02-11 21:43:503306 # Stubs for handling special syntax in the root DEPS file.
3307 class _VarImpl:
3308 def __init__(self, local_scope):
3309 self._local_scope = local_scope
Daniel Cheng4dcdb6b2017-04-13 08:30:173310
Sam Maiera6e76d72022-02-11 21:43:503311 def Lookup(self, var_name):
3312 """Implements the Var syntax."""
3313 try:
3314 return self._local_scope['vars'][var_name]
3315 except KeyError:
3316 raise Exception('Var is not defined: %s' % var_name)
Daniel Cheng4dcdb6b2017-04-13 08:30:173317
Sam Maiera6e76d72022-02-11 21:43:503318 local_scope = {}
3319 global_scope = {
3320 'Var': _VarImpl(local_scope).Lookup,
3321 'Str': str,
3322 }
Dirk Pranke1b9e06382021-05-14 01:16:223323
Sam Maiera6e76d72022-02-11 21:43:503324 exec(contents, global_scope, local_scope)
3325 return local_scope
Daniel Cheng4dcdb6b2017-04-13 08:30:173326
3327
3328def _CalculateAddedDeps(os_path, old_contents, new_contents):
Sam Maiera6e76d72022-02-11 21:43:503329 """Helper method for CheckAddedDepsHaveTargetApprovals. Returns
3330 a set of DEPS entries that we should look up.
[email protected]14a6131c2014-01-08 01:15:413331
Sam Maiera6e76d72022-02-11 21:43:503332 For a directory (rather than a specific filename) we fake a path to
3333 a specific filename by adding /DEPS. This is chosen as a file that
3334 will seldom or never be subject to per-file include_rules.
3335 """
3336 # We ignore deps entries on auto-generated directories.
3337 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:083338
Sam Maiera6e76d72022-02-11 21:43:503339 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
3340 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
Daniel Cheng4dcdb6b2017-04-13 08:30:173341
Sam Maiera6e76d72022-02-11 21:43:503342 added_deps = new_deps.difference(old_deps)
Daniel Cheng4dcdb6b2017-04-13 08:30:173343
Sam Maiera6e76d72022-02-11 21:43:503344 results = set()
3345 for added_dep in added_deps:
3346 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
3347 continue
3348 # Assume that a rule that ends in .h is a rule for a specific file.
3349 if added_dep.endswith('.h'):
3350 results.add(added_dep)
3351 else:
3352 results.add(os_path.join(added_dep, 'DEPS'))
3353 return results
[email protected]f32e2d1e2013-07-26 21:39:083354
Stephanie Kimec4f55a2024-04-24 16:54:023355def CheckForNewDEPSDownloadFromGoogleStorageHooks(input_api, output_api):
3356 """Checks that there are no new download_from_google_storage hooks"""
3357 for f in input_api.AffectedFiles(include_deletes=False):
3358 if f.LocalPath() == 'DEPS':
3359 old_hooks = _ParseDeps('\n'.join(f.OldContents()))['hooks']
3360 new_hooks = _ParseDeps('\n'.join(f.NewContents()))['hooks']
3361 old_name_to_hook = {hook['name']: hook for hook in old_hooks}
3362 new_name_to_hook = {hook['name']: hook for hook in new_hooks}
3363 added_hook_names = set(new_name_to_hook.keys()) - set(
3364 old_name_to_hook.keys())
3365 if not added_hook_names:
3366 return []
3367 new_download_from_google_storage_hooks = []
3368 for new_hook in added_hook_names:
3369 hook = new_name_to_hook[new_hook]
3370 action_cmd = hook['action']
3371 if any('download_from_google_storage' in arg
3372 for arg in action_cmd):
3373 new_download_from_google_storage_hooks.append(new_hook)
3374 if new_download_from_google_storage_hooks:
3375 return [
3376 output_api.PresubmitError(
3377 'Please do not add new download_from_google_storage '
3378 'hooks. Instead, add a `gcs` dep_type entry to `deps`. '
3379 'See https://chromium.googlesource.com/chromium/src.git'
3380 '/+/refs/heads/main/docs/gcs_dependencies.md for more '
3381 'info. Added hooks:',
3382 items=new_download_from_google_storage_hooks)
3383 ]
3384 return []
3385
[email protected]f32e2d1e2013-07-26 21:39:083386
Rasika Navarangec2d33d22024-05-23 15:19:023387def CheckEachPerfettoTestDataFileHasDepsEntry(input_api, output_api):
3388 test_data_filter = lambda f: input_api.FilterSourceFile(
Rasika Navarange08e542162024-05-31 13:31:263389 f, files_to_check=[r'^base/tracing/test/data_sha256/.*\.sha256'])
Rasika Navarangec2d33d22024-05-23 15:19:023390 if not any(input_api.AffectedFiles(file_filter=test_data_filter)):
3391 return []
3392
3393 # Find DEPS entry
3394 deps_entry = []
3395 for f in input_api.AffectedFiles(include_deletes=False):
3396 if f.LocalPath() == 'DEPS':
3397 new_deps = _ParseDeps('\n'.join(f.NewContents()))['deps']
3398 deps_entry = new_deps['src/base/tracing/test/data']
3399 if not deps_entry:
Rasika Navarange08e542162024-05-31 13:31:263400 # TODO(312895063):Add back error when .sha256 files have been moved.
3401 return [output_api.PresubmitNotifyResult(
Rasika Navarangec2d33d22024-05-23 15:19:023402 'You must update the DEPS file when you update a '
Rasika Navarange08e542162024-05-31 13:31:263403 '.sha256 file in base/tracing/test/data_sha256'
Rasika Navarangec2d33d22024-05-23 15:19:023404 )]
3405
3406 output = []
3407 for f in input_api.AffectedFiles(file_filter=test_data_filter):
3408 objects = deps_entry['objects']
3409 if not f.NewContents():
3410 # Deleted file so check that DEPS entry removed
3411 sha256_from_file = f.OldContents()[0]
3412 object_entry = next(
3413 (item for item in objects if item["sha256sum"] == sha256_from_file),
3414 None)
3415 if object_entry:
3416 output.append(output_api.PresubmitError(
3417 'You deleted %s so you must also remove the corresponding DEPS entry.'
3418 % f.LocalPath()
3419 ))
3420 continue
3421
3422 sha256_from_file = f.NewContents()[0]
3423 object_entry = next(
3424 (item for item in objects if item["sha256sum"] == sha256_from_file),
3425 None)
3426 if not object_entry:
3427 output.append(output_api.PresubmitError(
3428 'No corresponding DEPS entry found for %s. '
3429 'Run `base/tracing/test/test_data.py get_deps --filepath %s` '
3430 'to generate the DEPS entry.'
3431 % (f.LocalPath(), f.LocalPath())
3432 ))
3433
3434 if output:
3435 output.append(output_api.PresubmitError(
3436 'The DEPS entry for `src/base/tracing/test/data` in the DEPS file has not been '
3437 'updated properly. Run `base/tracing/test/test_data.py get_all_deps` to see what '
3438 'the DEPS entry should look like.'
3439 ))
3440 return output
3441
3442
Saagar Sanghavifceeaae2020-08-12 16:40:363443def CheckAddedDepsHaveTargetApprovals(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503444 """When a dependency prefixed with + is added to a DEPS file, we
3445 want to make sure that the change is reviewed by an OWNER of the
3446 target file or directory, to avoid layering violations from being
3447 introduced. This check verifies that this happens.
3448 """
3449 # We rely on Gerrit's code-owners to check approvals.
3450 # input_api.gerrit is always set for Chromium, but other projects
3451 # might not use Gerrit.
Bruce Dawson344ab262022-06-04 11:35:103452 if not input_api.gerrit or input_api.no_diffs:
Sam Maiera6e76d72022-02-11 21:43:503453 return []
Bruce Dawsonb357aeb2022-08-09 15:38:303454 if 'PRESUBMIT_SKIP_NETWORK' in input_api.environ:
Sam Maiera6e76d72022-02-11 21:43:503455 return []
Bruce Dawsonb357aeb2022-08-09 15:38:303456 try:
3457 if (input_api.change.issue and
3458 input_api.gerrit.IsOwnersOverrideApproved(
3459 input_api.change.issue)):
3460 # Skip OWNERS check when Owners-Override label is approved. This is
3461 # intended for global owners, trusted bots, and on-call sheriffs.
3462 # Review is still required for these changes.
3463 return []
3464 except Exception as e:
Sam Maier4cef9242022-10-03 14:21:243465 return [output_api.PresubmitPromptWarning(
3466 'Failed to retrieve owner override status - %s' % str(e))]
Edward Lesmes6fba51082021-01-20 04:20:233467
Sam Maiera6e76d72022-02-11 21:43:503468 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:243469
Bruce Dawson40fece62022-09-16 19:58:313470 # Consistently use / as path separator to simplify the writing of regex
3471 # expressions.
Sam Maiera6e76d72022-02-11 21:43:503472 file_filter = lambda f: not input_api.re.match(
Bruce Dawson40fece62022-09-16 19:58:313473 r"^third_party/blink/.*",
3474 f.LocalPath().replace(input_api.os_path.sep, '/'))
Sam Maiera6e76d72022-02-11 21:43:503475 for f in input_api.AffectedFiles(include_deletes=False,
3476 file_filter=file_filter):
3477 filename = input_api.os_path.basename(f.LocalPath())
3478 if filename == 'DEPS':
3479 virtual_depended_on_files.update(
3480 _CalculateAddedDeps(input_api.os_path,
3481 '\n'.join(f.OldContents()),
3482 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:553483
Sam Maiera6e76d72022-02-11 21:43:503484 if not virtual_depended_on_files:
3485 return []
[email protected]e871964c2013-05-13 14:14:553486
Sam Maiera6e76d72022-02-11 21:43:503487 if input_api.is_committing:
3488 if input_api.tbr:
3489 return [
3490 output_api.PresubmitNotifyResult(
3491 '--tbr was specified, skipping OWNERS check for DEPS additions'
3492 )
3493 ]
Daniel Cheng3008dc12022-05-13 04:02:113494 # TODO(dcheng): Make this generate an error on dry runs if the reviewer
3495 # is not added, to prevent review serialization.
Sam Maiera6e76d72022-02-11 21:43:503496 if input_api.dry_run:
3497 return [
3498 output_api.PresubmitNotifyResult(
3499 'This is a dry run, skipping OWNERS check for DEPS additions'
3500 )
3501 ]
3502 if not input_api.change.issue:
3503 return [
3504 output_api.PresubmitError(
3505 "DEPS approval by OWNERS check failed: this change has "
3506 "no change number, so we can't check it for approvals.")
3507 ]
3508 output = output_api.PresubmitError
[email protected]14a6131c2014-01-08 01:15:413509 else:
Sam Maiera6e76d72022-02-11 21:43:503510 output = output_api.PresubmitNotifyResult
[email protected]e871964c2013-05-13 14:14:553511
Sam Maiera6e76d72022-02-11 21:43:503512 owner_email, reviewers = (
3513 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
3514 input_api, None, approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:553515
Sam Maiera6e76d72022-02-11 21:43:503516 owner_email = owner_email or input_api.change.author_email
3517
3518 approval_status = input_api.owners_client.GetFilesApprovalStatus(
3519 virtual_depended_on_files, reviewers.union([owner_email]), [])
3520 missing_files = [
3521 f for f in virtual_depended_on_files
3522 if approval_status[f] != input_api.owners_client.APPROVED
3523 ]
3524
3525 # We strip the /DEPS part that was added by
3526 # _FilesToCheckForIncomingDeps to fake a path to a file in a
3527 # directory.
3528 def StripDeps(path):
3529 start_deps = path.rfind('/DEPS')
3530 if start_deps != -1:
3531 return path[:start_deps]
3532 else:
3533 return path
3534
3535 unapproved_dependencies = [
3536 "'+%s'," % StripDeps(path) for path in missing_files
3537 ]
3538
3539 if unapproved_dependencies:
3540 output_list = [
3541 output(
3542 'You need LGTM from owners of depends-on paths in DEPS that were '
3543 'modified in this CL:\n %s' %
3544 '\n '.join(sorted(unapproved_dependencies)))
3545 ]
3546 suggested_owners = input_api.owners_client.SuggestOwners(
3547 missing_files, exclude=[owner_email])
3548 output_list.append(
3549 output('Suggested missing target path OWNERS:\n %s' %
3550 '\n '.join(suggested_owners or [])))
3551 return output_list
3552
3553 return []
[email protected]e871964c2013-05-13 14:14:553554
3555
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493556# TODO: add unit tests.
Saagar Sanghavifceeaae2020-08-12 16:40:363557def CheckSpamLogging(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503558 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
3559 files_to_skip = (
3560 _EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
3561 input_api.DEFAULT_FILES_TO_SKIP + (
Jaewon Jung2f323bb2022-12-07 23:55:013562 r"^base/fuchsia/scoped_fx_logger\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313563 r"^base/logging\.h$",
3564 r"^base/logging\.cc$",
3565 r"^base/task/thread_pool/task_tracker\.cc$",
3566 r"^chrome/app/chrome_main_delegate\.cc$",
Yao Li359937b2023-02-15 23:43:033567 r"^chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer\.cc$",
3568 r"^chrome/browser/ash/policy/remote_commands/user_command_arc_job\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313569 r"^chrome/browser/chrome_browser_main\.cc$",
3570 r"^chrome/browser/ui/startup/startup_browser_creator\.cc$",
3571 r"^chrome/browser/browser_switcher/bho/.*",
3572 r"^chrome/browser/diagnostics/diagnostics_writer\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313573 r"^chrome/chrome_elf/dll_hash/dll_hash_main\.cc$",
3574 r"^chrome/installer/setup/.*",
3575 r"^chromecast/",
Vigen Issahhanjane2d93822023-06-30 15:57:203576 r"^components/cast",
Bruce Dawson40fece62022-09-16 19:58:313577 r"^components/media_control/renderer/media_playback_options\.cc$",
Salma Elmahallawy52976452023-01-27 17:04:493578 r"^components/policy/core/common/policy_logger\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313579 r"^components/viz/service/display/"
Sam Maiera6e76d72022-02-11 21:43:503580 r"overlay_strategy_underlay_cast\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313581 r"^components/zucchini/.*",
Sam Maiera6e76d72022-02-11 21:43:503582 # TODO(peter): Remove exception. https://crbug.com/534537
Bruce Dawson40fece62022-09-16 19:58:313583 r"^content/browser/notifications/"
Sam Maiera6e76d72022-02-11 21:43:503584 r"notification_event_dispatcher_impl\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313585 r"^content/common/gpu/client/gl_helper_benchmark\.cc$",
3586 r"^courgette/courgette_minimal_tool\.cc$",
3587 r"^courgette/courgette_tool\.cc$",
3588 r"^extensions/renderer/logging_native_handler\.cc$",
3589 r"^fuchsia_web/common/init_logging\.cc$",
3590 r"^fuchsia_web/runners/common/web_component\.cc$",
Caroline Liua7050132023-02-13 22:23:153591 r"^fuchsia_web/shell/.*\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313592 r"^headless/app/headless_shell\.cc$",
3593 r"^ipc/ipc_logging\.cc$",
3594 r"^native_client_sdk/",
3595 r"^remoting/base/logging\.h$",
3596 r"^remoting/host/.*",
3597 r"^sandbox/linux/.*",
Austin Sullivana6054e02024-05-20 16:31:293598 r"^services/webnn/tflite/graph_impl_tflite\.cc$",
3599 r"^services/webnn/coreml/graph_impl_coreml\.mm$",
Bruce Dawson40fece62022-09-16 19:58:313600 r"^storage/browser/file_system/dump_file_system\.cc$",
3601 r"^tools/",
3602 r"^ui/base/resource/data_pack\.cc$",
3603 r"^ui/aura/bench/bench_main\.cc$",
3604 r"^ui/ozone/platform/cast/",
3605 r"^ui/base/x/xwmstartupcheck/"
Sam Maiera6e76d72022-02-11 21:43:503606 r"xwmstartupcheck\.cc$"))
3607 source_file_filter = lambda x: input_api.FilterSourceFile(
3608 x, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
[email protected]85218562013-11-22 07:41:403609
Sam Maiera6e76d72022-02-11 21:43:503610 log_info = set([])
3611 printf = set([])
[email protected]85218562013-11-22 07:41:403612
Sam Maiera6e76d72022-02-11 21:43:503613 for f in input_api.AffectedSourceFiles(source_file_filter):
3614 for _, line in f.ChangedContents():
3615 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
3616 log_info.add(f.LocalPath())
3617 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
3618 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:373619
Sam Maiera6e76d72022-02-11 21:43:503620 if input_api.re.search(r"\bprintf\(", line):
3621 printf.add(f.LocalPath())
3622 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
3623 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:403624
Sam Maiera6e76d72022-02-11 21:43:503625 if log_info:
3626 return [
3627 output_api.PresubmitError(
3628 'These files spam the console log with LOG(INFO):',
3629 items=log_info)
3630 ]
3631 if printf:
3632 return [
3633 output_api.PresubmitError(
3634 'These files spam the console log with printf/fprintf:',
3635 items=printf)
3636 ]
3637 return []
[email protected]85218562013-11-22 07:41:403638
3639
Saagar Sanghavifceeaae2020-08-12 16:40:363640def CheckForAnonymousVariables(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503641 """These types are all expected to hold locks while in scope and
3642 so should never be anonymous (which causes them to be immediately
3643 destroyed)."""
3644 they_who_must_be_named = [
3645 'base::AutoLock',
3646 'base::AutoReset',
3647 'base::AutoUnlock',
3648 'SkAutoAlphaRestore',
3649 'SkAutoBitmapShaderInstall',
3650 'SkAutoBlitterChoose',
3651 'SkAutoBounderCommit',
3652 'SkAutoCallProc',
3653 'SkAutoCanvasRestore',
3654 'SkAutoCommentBlock',
3655 'SkAutoDescriptor',
3656 'SkAutoDisableDirectionCheck',
3657 'SkAutoDisableOvalCheck',
3658 'SkAutoFree',
3659 'SkAutoGlyphCache',
3660 'SkAutoHDC',
3661 'SkAutoLockColors',
3662 'SkAutoLockPixels',
3663 'SkAutoMalloc',
3664 'SkAutoMaskFreeImage',
3665 'SkAutoMutexAcquire',
3666 'SkAutoPathBoundsUpdate',
3667 'SkAutoPDFRelease',
3668 'SkAutoRasterClipValidate',
3669 'SkAutoRef',
3670 'SkAutoTime',
3671 'SkAutoTrace',
3672 'SkAutoUnref',
3673 ]
3674 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
3675 # bad: base::AutoLock(lock.get());
3676 # not bad: base::AutoLock lock(lock.get());
3677 bad_pattern = input_api.re.compile(anonymous)
3678 # good: new base::AutoLock(lock.get())
3679 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
3680 errors = []
[email protected]49aa76a2013-12-04 06:59:163681
Sam Maiera6e76d72022-02-11 21:43:503682 for f in input_api.AffectedFiles():
3683 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
3684 continue
3685 for linenum, line in f.ChangedContents():
3686 if bad_pattern.search(line) and not good_pattern.search(line):
3687 errors.append('%s:%d' % (f.LocalPath(), linenum))
[email protected]49aa76a2013-12-04 06:59:163688
Sam Maiera6e76d72022-02-11 21:43:503689 if errors:
3690 return [
3691 output_api.PresubmitError(
3692 'These lines create anonymous variables that need to be named:',
3693 items=errors)
3694 ]
3695 return []
[email protected]49aa76a2013-12-04 06:59:163696
3697
Saagar Sanghavifceeaae2020-08-12 16:40:363698def CheckUniquePtrOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503699 # Returns whether |template_str| is of the form <T, U...> for some types T
Glen Robertson9142ffd72024-05-16 01:37:473700 # and U, or is invalid due to mismatched angle bracket pairs. Assumes that
3701 # |template_str| is already in the form <...>.
3702 def HasMoreThanOneArgOrInvalid(template_str):
Sam Maiera6e76d72022-02-11 21:43:503703 # Level of <...> nesting.
3704 nesting = 0
3705 for c in template_str:
3706 if c == '<':
3707 nesting += 1
3708 elif c == '>':
3709 nesting -= 1
3710 elif c == ',' and nesting == 1:
3711 return True
Glen Robertson9142ffd72024-05-16 01:37:473712 if nesting != 0:
3713 # Invalid.
3714 return True
Sam Maiera6e76d72022-02-11 21:43:503715 return False
Vaclav Brozekb7fadb692018-08-30 06:39:533716
Sam Maiera6e76d72022-02-11 21:43:503717 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
3718 sources = lambda affected_file: input_api.FilterSourceFile(
3719 affected_file,
3720 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
3721 DEFAULT_FILES_TO_SKIP),
3722 files_to_check=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:553723
Sam Maiera6e76d72022-02-11 21:43:503724 # Pattern to capture a single "<...>" block of template arguments. It can
3725 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
3726 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
3727 # latter would likely require counting that < and > match, which is not
3728 # expressible in regular languages. Should the need arise, one can introduce
3729 # limited counting (matching up to a total number of nesting depth), which
3730 # should cover all practical cases for already a low nesting limit.
3731 template_arg_pattern = (
3732 r'<[^>]*' # Opening block of <.
3733 r'>([^<]*>)?') # Closing block of >.
3734 # Prefix expressing that whatever follows is not already inside a <...>
3735 # block.
3736 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
3737 null_construct_pattern = input_api.re.compile(
3738 not_inside_template_arg_pattern + r'\bstd::unique_ptr' +
3739 template_arg_pattern + r'\(\)')
Vaclav Brozeka54c528b2018-04-06 19:23:553740
Sam Maiera6e76d72022-02-11 21:43:503741 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
3742 template_arg_no_array_pattern = (
3743 r'<[^>]*[^]]' # Opening block of <.
3744 r'>([^(<]*[^]]>)?') # Closing block of >.
3745 # Prefix saying that what follows is the start of an expression.
3746 start_of_expr_pattern = r'(=|\breturn|^)\s*'
3747 # Suffix saying that what follows are call parentheses with a non-empty list
3748 # of arguments.
3749 nonempty_arg_list_pattern = r'\(([^)]|$)'
3750 # Put the template argument into a capture group for deeper examination later.
3751 return_construct_pattern = input_api.re.compile(
3752 start_of_expr_pattern + r'std::unique_ptr' + '(?P<template_arg>' +
3753 template_arg_no_array_pattern + ')' + nonempty_arg_list_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:553754
Sam Maiera6e76d72022-02-11 21:43:503755 problems_constructor = []
3756 problems_nullptr = []
3757 for f in input_api.AffectedSourceFiles(sources):
3758 for line_number, line in f.ChangedContents():
3759 # Disallow:
3760 # return std::unique_ptr<T>(foo);
3761 # bar = std::unique_ptr<T>(foo);
3762 # But allow:
3763 # return std::unique_ptr<T[]>(foo);
3764 # bar = std::unique_ptr<T[]>(foo);
3765 # And also allow cases when the second template argument is present. Those
3766 # cases cannot be handled by std::make_unique:
3767 # return std::unique_ptr<T, U>(foo);
3768 # bar = std::unique_ptr<T, U>(foo);
3769 local_path = f.LocalPath()
3770 return_construct_result = return_construct_pattern.search(line)
Glen Robertson9142ffd72024-05-16 01:37:473771 if return_construct_result and not HasMoreThanOneArgOrInvalid(
Sam Maiera6e76d72022-02-11 21:43:503772 return_construct_result.group('template_arg')):
3773 problems_constructor.append(
3774 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3775 # Disallow:
3776 # std::unique_ptr<T>()
3777 if null_construct_pattern.search(line):
3778 problems_nullptr.append(
3779 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Vaclav Brozek851d9602018-04-04 16:13:053780
Sam Maiera6e76d72022-02-11 21:43:503781 errors = []
3782 if problems_nullptr:
3783 errors.append(
3784 output_api.PresubmitPromptWarning(
3785 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
3786 problems_nullptr))
3787 if problems_constructor:
3788 errors.append(
3789 output_api.PresubmitError(
3790 'The following files use explicit std::unique_ptr constructor. '
3791 'Use std::make_unique<T>() instead, or use base::WrapUnique if '
3792 'std::make_unique is not an option.', problems_constructor))
3793 return errors
Peter Kasting4844e46e2018-02-23 07:27:103794
3795
Saagar Sanghavifceeaae2020-08-12 16:40:363796def CheckUserActionUpdate(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503797 """Checks if any new user action has been added."""
3798 if any('actions.xml' == input_api.os_path.basename(f)
3799 for f in input_api.LocalPaths()):
3800 # If actions.xml is already included in the changelist, the PRESUBMIT
3801 # for actions.xml will do a more complete presubmit check.
3802 return []
3803
3804 file_inclusion_pattern = [r'.*\.(cc|mm)$']
3805 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
3806 input_api.DEFAULT_FILES_TO_SKIP)
3807 file_filter = lambda f: input_api.FilterSourceFile(
3808 f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
3809
3810 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
3811 current_actions = None
3812 for f in input_api.AffectedFiles(file_filter=file_filter):
3813 for line_num, line in f.ChangedContents():
3814 match = input_api.re.search(action_re, line)
3815 if match:
3816 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
3817 # loaded only once.
3818 if not current_actions:
Bruce Dawson6cb2d4d2023-03-01 21:35:093819 with open('tools/metrics/actions/actions.xml',
3820 encoding='utf-8') as actions_f:
Sam Maiera6e76d72022-02-11 21:43:503821 current_actions = actions_f.read()
3822 # Search for the matched user action name in |current_actions|.
3823 for action_name in match.groups():
3824 action = 'name="{0}"'.format(action_name)
3825 if action not in current_actions:
3826 return [
3827 output_api.PresubmitPromptWarning(
3828 'File %s line %d: %s is missing in '
3829 'tools/metrics/actions/actions.xml. Please run '
3830 'tools/metrics/actions/extract_actions.py to update.'
3831 % (f.LocalPath(), line_num, action_name))
3832 ]
[email protected]999261d2014-03-03 20:08:083833 return []
3834
[email protected]999261d2014-03-03 20:08:083835
Daniel Cheng13ca61a882017-08-25 15:11:253836def _ImportJSONCommentEater(input_api):
Sam Maiera6e76d72022-02-11 21:43:503837 import sys
3838 sys.path = sys.path + [
3839 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
3840 'json_comment_eater')
3841 ]
3842 import json_comment_eater
3843 return json_comment_eater
Daniel Cheng13ca61a882017-08-25 15:11:253844
3845
[email protected]99171a92014-06-03 08:44:473846def _GetJSONParseError(input_api, filename, eat_comments=True):
dchenge07de812016-06-20 19:27:173847 try:
Sam Maiera6e76d72022-02-11 21:43:503848 contents = input_api.ReadFile(filename)
3849 if eat_comments:
3850 json_comment_eater = _ImportJSONCommentEater(input_api)
3851 contents = json_comment_eater.Nom(contents)
dchenge07de812016-06-20 19:27:173852
Sam Maiera6e76d72022-02-11 21:43:503853 input_api.json.loads(contents)
3854 except ValueError as e:
3855 return e
Andrew Grieve4deedb12022-02-03 21:34:503856 return None
3857
3858
Sam Maiera6e76d72022-02-11 21:43:503859def _GetIDLParseError(input_api, filename):
3860 try:
3861 contents = input_api.ReadFile(filename)
Devlin Croninf7582a12022-04-21 21:14:283862 for i, char in enumerate(contents):
Daniel Chenga37c03db2022-05-12 17:20:343863 if not char.isascii():
3864 return (
3865 'Non-ascii character "%s" (ord %d) found at offset %d.' %
3866 (char, ord(char), i))
Sam Maiera6e76d72022-02-11 21:43:503867 idl_schema = input_api.os_path.join(input_api.PresubmitLocalPath(),
3868 'tools', 'json_schema_compiler',
3869 'idl_schema.py')
3870 process = input_api.subprocess.Popen(
Bruce Dawson679fb082022-04-14 00:47:283871 [input_api.python3_executable, idl_schema],
Sam Maiera6e76d72022-02-11 21:43:503872 stdin=input_api.subprocess.PIPE,
3873 stdout=input_api.subprocess.PIPE,
3874 stderr=input_api.subprocess.PIPE,
3875 universal_newlines=True)
3876 (_, error) = process.communicate(input=contents)
3877 return error or None
3878 except ValueError as e:
3879 return e
agrievef32bcc72016-04-04 14:57:403880
agrievef32bcc72016-04-04 14:57:403881
Sam Maiera6e76d72022-02-11 21:43:503882def CheckParseErrors(input_api, output_api):
3883 """Check that IDL and JSON files do not contain syntax errors."""
3884 actions = {
3885 '.idl': _GetIDLParseError,
3886 '.json': _GetJSONParseError,
3887 }
3888 # Most JSON files are preprocessed and support comments, but these do not.
3889 json_no_comments_patterns = [
Bruce Dawson40fece62022-09-16 19:58:313890 r'^testing/',
Sam Maiera6e76d72022-02-11 21:43:503891 ]
3892 # Only run IDL checker on files in these directories.
3893 idl_included_patterns = [
Bruce Dawson40fece62022-09-16 19:58:313894 r'^chrome/common/extensions/api/',
3895 r'^extensions/common/api/',
Sam Maiera6e76d72022-02-11 21:43:503896 ]
agrievef32bcc72016-04-04 14:57:403897
Sam Maiera6e76d72022-02-11 21:43:503898 def get_action(affected_file):
3899 filename = affected_file.LocalPath()
3900 return actions.get(input_api.os_path.splitext(filename)[1])
agrievef32bcc72016-04-04 14:57:403901
Sam Maiera6e76d72022-02-11 21:43:503902 def FilterFile(affected_file):
3903 action = get_action(affected_file)
3904 if not action:
3905 return False
3906 path = affected_file.LocalPath()
agrievef32bcc72016-04-04 14:57:403907
Sam Maiera6e76d72022-02-11 21:43:503908 if _MatchesFile(input_api,
3909 _KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS, path):
3910 return False
3911
3912 if (action == _GetIDLParseError
3913 and not _MatchesFile(input_api, idl_included_patterns, path)):
3914 return False
3915 return True
3916
3917 results = []
3918 for affected_file in input_api.AffectedFiles(file_filter=FilterFile,
3919 include_deletes=False):
3920 action = get_action(affected_file)
3921 kwargs = {}
3922 if (action == _GetJSONParseError
3923 and _MatchesFile(input_api, json_no_comments_patterns,
3924 affected_file.LocalPath())):
3925 kwargs['eat_comments'] = False
3926 parse_error = action(input_api, affected_file.AbsoluteLocalPath(),
3927 **kwargs)
3928 if parse_error:
3929 results.append(
3930 output_api.PresubmitError(
3931 '%s could not be parsed: %s' %
3932 (affected_file.LocalPath(), parse_error)))
3933 return results
3934
3935
3936def CheckJavaStyle(input_api, output_api):
3937 """Runs checkstyle on changed java files and returns errors if any exist."""
3938
3939 # Return early if no java files were modified.
3940 if not any(
3941 _IsJavaFile(input_api, f.LocalPath())
3942 for f in input_api.AffectedFiles()):
3943 return []
3944
3945 import sys
3946 original_sys_path = sys.path
3947 try:
3948 sys.path = sys.path + [
3949 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
3950 'android', 'checkstyle')
3951 ]
3952 import checkstyle
3953 finally:
3954 # Restore sys.path to what it was before.
3955 sys.path = original_sys_path
3956
Andrew Grieve4f88e3ca2022-11-22 19:09:203957 return checkstyle.run_presubmit(
Sam Maiera6e76d72022-02-11 21:43:503958 input_api,
3959 output_api,
Sam Maiera6e76d72022-02-11 21:43:503960 files_to_skip=_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP)
3961
3962
3963def CheckPythonDevilInit(input_api, output_api):
3964 """Checks to make sure devil is initialized correctly in python scripts."""
3965 script_common_initialize_pattern = input_api.re.compile(
3966 r'script_common\.InitializeEnvironment\(')
3967 devil_env_config_initialize = input_api.re.compile(
3968 r'devil_env\.config\.Initialize\(')
3969
3970 errors = []
3971
3972 sources = lambda affected_file: input_api.FilterSourceFile(
3973 affected_file,
3974 files_to_skip=(_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP + (
Bruce Dawson40fece62022-09-16 19:58:313975 r'^build/android/devil_chromium\.py',
Sven Zheng8e079562024-05-10 20:11:063976 r'^tools/bisect-builds\.py',
Bruce Dawson40fece62022-09-16 19:58:313977 r'^third_party/.*',
Sam Maiera6e76d72022-02-11 21:43:503978 )),
3979 files_to_check=[r'.*\.py$'])
3980
3981 for f in input_api.AffectedSourceFiles(sources):
3982 for line_num, line in f.ChangedContents():
3983 if (script_common_initialize_pattern.search(line)
3984 or devil_env_config_initialize.search(line)):
3985 errors.append("%s:%d" % (f.LocalPath(), line_num))
3986
3987 results = []
3988
3989 if errors:
3990 results.append(
3991 output_api.PresubmitError(
3992 'Devil initialization should always be done using '
3993 'devil_chromium.Initialize() in the chromium project, to use better '
3994 'defaults for dependencies (ex. up-to-date version of adb).',
3995 errors))
3996
3997 return results
3998
3999
4000def _MatchesFile(input_api, patterns, path):
Bruce Dawson40fece62022-09-16 19:58:314001 # Consistently use / as path separator to simplify the writing of regex
4002 # expressions.
4003 path = path.replace(input_api.os_path.sep, '/')
Sam Maiera6e76d72022-02-11 21:43:504004 for pattern in patterns:
4005 if input_api.re.search(pattern, path):
4006 return True
4007 return False
4008
4009
Daniel Chenga37c03db2022-05-12 17:20:344010def _ChangeHasSecurityReviewer(input_api, owners_file):
4011 """Returns True iff the CL has a reviewer from SECURITY_OWNERS.
Sam Maiera6e76d72022-02-11 21:43:504012
Daniel Chenga37c03db2022-05-12 17:20:344013 Args:
4014 input_api: The presubmit input API.
4015 owners_file: OWNERS file with required reviewers. Typically, this is
4016 something like ipc/SECURITY_OWNERS.
4017
4018 Note: if the presubmit is running for commit rather than for upload, this
4019 only returns True if a security reviewer has also approved the CL.
Sam Maiera6e76d72022-02-11 21:43:504020 """
Daniel Chengd88244472022-05-16 09:08:474021 # Owners-Override should bypass all additional OWNERS enforcement checks.
4022 # A CR+1 vote will still be required to land this change.
4023 if (input_api.change.issue and input_api.gerrit.IsOwnersOverrideApproved(
4024 input_api.change.issue)):
4025 return True
4026
Daniel Chenga37c03db2022-05-12 17:20:344027 owner_email, reviewers = (
4028 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
Daniel Cheng3008dc12022-05-13 04:02:114029 input_api,
4030 None,
4031 approval_needed=input_api.is_committing and not input_api.dry_run))
Sam Maiera6e76d72022-02-11 21:43:504032
Daniel Chenga37c03db2022-05-12 17:20:344033 security_owners = input_api.owners_client.ListOwners(owners_file)
4034 return any(owner in reviewers for owner in security_owners)
Sam Maiera6e76d72022-02-11 21:43:504035
Daniel Chenga37c03db2022-05-12 17:20:344036
4037@dataclass
Daniel Cheng171dad8d2022-05-21 00:40:254038class _SecurityProblemWithItems:
4039 problem: str
4040 items: Sequence[str]
4041
4042
4043@dataclass
Daniel Chenga37c03db2022-05-12 17:20:344044class _MissingSecurityOwnersResult:
Daniel Cheng171dad8d2022-05-21 00:40:254045 owners_file_problems: Sequence[_SecurityProblemWithItems]
Daniel Chenga37c03db2022-05-12 17:20:344046 has_security_sensitive_files: bool
Daniel Cheng171dad8d2022-05-21 00:40:254047 missing_reviewer_problem: Optional[_SecurityProblemWithItems]
Daniel Chenga37c03db2022-05-12 17:20:344048
4049
4050def _FindMissingSecurityOwners(input_api,
4051 output_api,
4052 file_patterns: Sequence[str],
4053 excluded_patterns: Sequence[str],
4054 required_owners_file: str,
4055 custom_rule_function: Optional[Callable] = None
4056 ) -> _MissingSecurityOwnersResult:
4057 """Find OWNERS files missing per-file rules for security-sensitive files.
4058
4059 Args:
4060 input_api: the PRESUBMIT input API object.
4061 output_api: the PRESUBMIT output API object.
4062 file_patterns: basename patterns that require a corresponding per-file
4063 security restriction.
4064 excluded_patterns: path patterns that should be exempted from
4065 requiring a security restriction.
4066 required_owners_file: path to the required OWNERS file, e.g.
4067 ipc/SECURITY_OWNERS
4068 cc_alias: If not None, email that will be CCed automatically if the
4069 change contains security-sensitive files, as determined by
4070 `file_patterns` and `excluded_patterns`.
4071 custom_rule_function: If not None, will be called with `input_api` and
4072 the current file under consideration. Returning True will add an
4073 exact match per-file rule check for the current file.
4074 """
4075
4076 # `to_check` is a mapping of an OWNERS file path to Patterns.
4077 #
4078 # Patterns is a dictionary mapping glob patterns (suitable for use in
4079 # per-file rules) to a PatternEntry.
4080 #
Sam Maiera6e76d72022-02-11 21:43:504081 # PatternEntry is a dictionary with two keys:
4082 # - 'files': the files that are matched by this pattern
4083 # - 'rules': the per-file rules needed for this pattern
Daniel Chenga37c03db2022-05-12 17:20:344084 #
Sam Maiera6e76d72022-02-11 21:43:504085 # For example, if we expect OWNERS file to contain rules for *.mojom and
4086 # *_struct_traits*.*, Patterns might look like this:
4087 # {
4088 # '*.mojom': {
4089 # 'files': ...,
4090 # 'rules': [
4091 # 'per-file *.mojom=set noparent',
4092 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
4093 # ],
4094 # },
4095 # '*_struct_traits*.*': {
4096 # 'files': ...,
4097 # 'rules': [
4098 # 'per-file *_struct_traits*.*=set noparent',
4099 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
4100 # ],
4101 # },
4102 # }
4103 to_check = {}
Daniel Chenga37c03db2022-05-12 17:20:344104 files_to_review = []
Sam Maiera6e76d72022-02-11 21:43:504105
Daniel Chenga37c03db2022-05-12 17:20:344106 def AddPatternToCheck(file, pattern):
Sam Maiera6e76d72022-02-11 21:43:504107 owners_file = input_api.os_path.join(
Daniel Chengd88244472022-05-16 09:08:474108 input_api.os_path.dirname(file.LocalPath()), 'OWNERS')
Sam Maiera6e76d72022-02-11 21:43:504109 if owners_file not in to_check:
4110 to_check[owners_file] = {}
4111 if pattern not in to_check[owners_file]:
4112 to_check[owners_file][pattern] = {
4113 'files': [],
4114 'rules': [
Daniel Chenga37c03db2022-05-12 17:20:344115 f'per-file {pattern}=set noparent',
4116 f'per-file {pattern}=file://{required_owners_file}',
Sam Maiera6e76d72022-02-11 21:43:504117 ]
4118 }
Daniel Chenged57a162022-05-25 02:56:344119 to_check[owners_file][pattern]['files'].append(file.LocalPath())
Daniel Chenga37c03db2022-05-12 17:20:344120 files_to_review.append(file.LocalPath())
Sam Maiera6e76d72022-02-11 21:43:504121
Daniel Chenga37c03db2022-05-12 17:20:344122 # Only enforce security OWNERS rules for a directory if that directory has a
4123 # file that matches `file_patterns`. For example, if a directory only
4124 # contains *.mojom files and no *_messages*.h files, the check should only
4125 # ensure that rules for *.mojom files are present.
4126 for file in input_api.AffectedFiles(include_deletes=False):
4127 file_basename = input_api.os_path.basename(file.LocalPath())
4128 if custom_rule_function is not None and custom_rule_function(
4129 input_api, file):
4130 AddPatternToCheck(file, file_basename)
4131 continue
Sam Maiera6e76d72022-02-11 21:43:504132
Daniel Chenga37c03db2022-05-12 17:20:344133 if any(
4134 input_api.fnmatch.fnmatch(file.LocalPath(), pattern)
4135 for pattern in excluded_patterns):
Sam Maiera6e76d72022-02-11 21:43:504136 continue
4137
4138 for pattern in file_patterns:
Daniel Chenga37c03db2022-05-12 17:20:344139 # Unlike `excluded_patterns`, `file_patterns` is checked only against the
4140 # file's basename.
4141 if input_api.fnmatch.fnmatch(file_basename, pattern):
4142 AddPatternToCheck(file, pattern)
Sam Maiera6e76d72022-02-11 21:43:504143 break
4144
Daniel Chenga37c03db2022-05-12 17:20:344145 has_security_sensitive_files = bool(to_check)
Daniel Cheng171dad8d2022-05-21 00:40:254146
4147 # Check if any newly added lines in OWNERS files intersect with required
4148 # per-file OWNERS lines. If so, ensure that a security reviewer is included.
4149 # This is a hack, but is needed because the OWNERS check (by design) ignores
4150 # new OWNERS entries; otherwise, a non-owner could add someone as a new
4151 # OWNER and have that newly-added OWNER self-approve their own addition.
4152 newly_covered_files = []
4153 for file in input_api.AffectedFiles(include_deletes=False):
4154 if not file.LocalPath() in to_check:
4155 continue
4156 for _, line in file.ChangedContents():
4157 for _, entry in to_check[file.LocalPath()].items():
4158 if line in entry['rules']:
4159 newly_covered_files.extend(entry['files'])
4160
4161 missing_reviewer_problems = None
4162 if newly_covered_files and not _ChangeHasSecurityReviewer(
Daniel Chenga37c03db2022-05-12 17:20:344163 input_api, required_owners_file):
Daniel Cheng171dad8d2022-05-21 00:40:254164 missing_reviewer_problems = _SecurityProblemWithItems(
4165 f'Review from an owner in {required_owners_file} is required for '
4166 'the following newly-added files:',
4167 [f'{file}' for file in sorted(set(newly_covered_files))])
Sam Maiera6e76d72022-02-11 21:43:504168
4169 # Go through the OWNERS files to check, filtering out rules that are already
4170 # present in that OWNERS file.
4171 for owners_file, patterns in to_check.items():
4172 try:
Daniel Cheng171dad8d2022-05-21 00:40:254173 lines = set(
4174 input_api.ReadFile(
4175 input_api.os_path.join(input_api.change.RepositoryRoot(),
4176 owners_file)).splitlines())
4177 for entry in patterns.values():
4178 entry['rules'] = [
4179 rule for rule in entry['rules'] if rule not in lines
4180 ]
Sam Maiera6e76d72022-02-11 21:43:504181 except IOError:
4182 # No OWNERS file, so all the rules are definitely missing.
4183 continue
4184
4185 # All the remaining lines weren't found in OWNERS files, so emit an error.
Daniel Cheng171dad8d2022-05-21 00:40:254186 owners_file_problems = []
Daniel Chenga37c03db2022-05-12 17:20:344187
Sam Maiera6e76d72022-02-11 21:43:504188 for owners_file, patterns in to_check.items():
4189 missing_lines = []
4190 files = []
4191 for _, entry in patterns.items():
Daniel Chenged57a162022-05-25 02:56:344192 files.extend(entry['files'])
Sam Maiera6e76d72022-02-11 21:43:504193 missing_lines.extend(entry['rules'])
Sam Maiera6e76d72022-02-11 21:43:504194 if missing_lines:
Daniel Cheng171dad8d2022-05-21 00:40:254195 joined_missing_lines = '\n'.join(line for line in missing_lines)
4196 owners_file_problems.append(
4197 _SecurityProblemWithItems(
4198 'Found missing OWNERS lines for security-sensitive files. '
4199 f'Please add the following lines to {owners_file}:\n'
4200 f'{joined_missing_lines}\n\nTo ensure security review for:',
4201 files))
Daniel Chenga37c03db2022-05-12 17:20:344202
Daniel Cheng171dad8d2022-05-21 00:40:254203 return _MissingSecurityOwnersResult(owners_file_problems,
Daniel Chenga37c03db2022-05-12 17:20:344204 has_security_sensitive_files,
Daniel Cheng171dad8d2022-05-21 00:40:254205 missing_reviewer_problems)
Daniel Chenga37c03db2022-05-12 17:20:344206
4207
4208def _CheckChangeForIpcSecurityOwners(input_api, output_api):
4209 # Whether or not a file affects IPC is (mostly) determined by a simple list
4210 # of filename patterns.
4211 file_patterns = [
4212 # Legacy IPC:
4213 '*_messages.cc',
4214 '*_messages*.h',
4215 '*_param_traits*.*',
4216 # Mojo IPC:
4217 '*.mojom',
4218 '*_mojom_traits*.*',
4219 '*_type_converter*.*',
4220 # Android native IPC:
4221 '*.aidl',
4222 ]
4223
Daniel Chenga37c03db2022-05-12 17:20:344224 excluded_patterns = [
Daniel Cheng518943f2022-05-12 22:15:464225 # These third_party directories do not contain IPCs, but contain files
4226 # matching the above patterns, which trigger false positives.
Daniel Chenga37c03db2022-05-12 17:20:344227 'third_party/crashpad/*',
4228 'third_party/blink/renderer/platform/bindings/*',
4229 'third_party/protobuf/benchmarks/python/*',
4230 'third_party/win_build_output/*',
Daniel Chengd88244472022-05-16 09:08:474231 # Enum-only mojoms used for web metrics, so no security review needed.
4232 'third_party/blink/public/mojom/use_counter/metrics/*',
Daniel Chenga37c03db2022-05-12 17:20:344233 # These files are just used to communicate between class loaders running
4234 # in the same process.
4235 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
4236 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
4237 ]
4238
4239 def IsMojoServiceManifestFile(input_api, file):
4240 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
4241 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
4242 if not manifest_pattern.search(file.LocalPath()):
4243 return False
4244
4245 if test_manifest_pattern.search(file.LocalPath()):
4246 return False
4247
4248 # All actual service manifest files should contain at least one
4249 # qualified reference to service_manager::Manifest.
4250 return any('service_manager::Manifest' in line
4251 for line in file.NewContents())
4252
4253 return _FindMissingSecurityOwners(
4254 input_api,
4255 output_api,
4256 file_patterns,
4257 excluded_patterns,
4258 'ipc/SECURITY_OWNERS',
4259 custom_rule_function=IsMojoServiceManifestFile)
4260
4261
4262def _CheckChangeForFuchsiaSecurityOwners(input_api, output_api):
4263 file_patterns = [
4264 # Component specifications.
4265 '*.cml', # Component Framework v2.
4266 '*.cmx', # Component Framework v1.
4267
4268 # Fuchsia IDL protocol specifications.
4269 '*.fidl',
4270 ]
4271
4272 # Don't check for owners files for changes in these directories.
4273 excluded_patterns = [
4274 'third_party/crashpad/*',
4275 ]
4276
4277 return _FindMissingSecurityOwners(input_api, output_api, file_patterns,
4278 excluded_patterns,
4279 'build/fuchsia/SECURITY_OWNERS')
4280
4281
4282def CheckSecurityOwners(input_api, output_api):
4283 """Checks that various security-sensitive files have an IPC OWNERS rule."""
4284 ipc_results = _CheckChangeForIpcSecurityOwners(input_api, output_api)
4285 fuchsia_results = _CheckChangeForFuchsiaSecurityOwners(
4286 input_api, output_api)
4287
4288 if ipc_results.has_security_sensitive_files:
4289 output_api.AppendCC('[email protected]')
Sam Maiera6e76d72022-02-11 21:43:504290
4291 results = []
Daniel Chenga37c03db2022-05-12 17:20:344292
Daniel Cheng171dad8d2022-05-21 00:40:254293 missing_reviewer_problems = []
4294 if ipc_results.missing_reviewer_problem:
4295 missing_reviewer_problems.append(ipc_results.missing_reviewer_problem)
4296 if fuchsia_results.missing_reviewer_problem:
4297 missing_reviewer_problems.append(
4298 fuchsia_results.missing_reviewer_problem)
Daniel Chenga37c03db2022-05-12 17:20:344299
Daniel Cheng171dad8d2022-05-21 00:40:254300 # Missing reviewers are an error unless there's no issue number
4301 # associated with this branch; in that case, the presubmit is being run
4302 # with --all or --files.
4303 #
4304 # Note that upload should never be an error; otherwise, it would be
4305 # impossible to upload changes at all.
4306 if input_api.is_committing and input_api.change.issue:
4307 make_presubmit_message = output_api.PresubmitError
4308 else:
4309 make_presubmit_message = output_api.PresubmitNotifyResult
4310 for problem in missing_reviewer_problems:
Sam Maiera6e76d72022-02-11 21:43:504311 results.append(
Daniel Cheng171dad8d2022-05-21 00:40:254312 make_presubmit_message(problem.problem, items=problem.items))
Daniel Chenga37c03db2022-05-12 17:20:344313
Daniel Cheng171dad8d2022-05-21 00:40:254314 owners_file_problems = []
4315 owners_file_problems.extend(ipc_results.owners_file_problems)
4316 owners_file_problems.extend(fuchsia_results.owners_file_problems)
Daniel Chenga37c03db2022-05-12 17:20:344317
Daniel Cheng171dad8d2022-05-21 00:40:254318 for problem in owners_file_problems:
Daniel Cheng3008dc12022-05-13 04:02:114319 # Missing per-file rules are always an error. While swarming and caching
4320 # means that uploading a patchset with updated OWNERS files and sending
4321 # it to the CQ again should not have a large incremental cost, it is
4322 # still frustrating to discover the error only after the change has
4323 # already been uploaded.
Daniel Chenga37c03db2022-05-12 17:20:344324 results.append(
Daniel Cheng171dad8d2022-05-21 00:40:254325 output_api.PresubmitError(problem.problem, items=problem.items))
Sam Maiera6e76d72022-02-11 21:43:504326
4327 return results
4328
4329
4330def _GetFilesUsingSecurityCriticalFunctions(input_api):
4331 """Checks affected files for changes to security-critical calls. This
4332 function checks the full change diff, to catch both additions/changes
4333 and removals.
4334
4335 Returns a dict keyed by file name, and the value is a set of detected
4336 functions.
4337 """
4338 # Map of function pretty name (displayed in an error) to the pattern to
4339 # match it with.
4340 _PATTERNS_TO_CHECK = {
4341 'content::GetServiceSandboxType<>()': 'GetServiceSandboxType\\<'
4342 }
4343 _PATTERNS_TO_CHECK = {
4344 k: input_api.re.compile(v)
4345 for k, v in _PATTERNS_TO_CHECK.items()
4346 }
4347
Sam Maiera6e76d72022-02-11 21:43:504348 # We don't want to trigger on strings within this file.
4349 def presubmit_file_filter(f):
Daniel Chenga37c03db2022-05-12 17:20:344350 return 'PRESUBMIT.py' != input_api.os_path.split(f.LocalPath())[1]
Sam Maiera6e76d72022-02-11 21:43:504351
4352 # Scan all affected files for changes touching _FUNCTIONS_TO_CHECK.
4353 files_to_functions = {}
4354 for f in input_api.AffectedFiles(file_filter=presubmit_file_filter):
4355 diff = f.GenerateScmDiff()
4356 for line in diff.split('\n'):
4357 # Not using just RightHandSideLines() because removing a
4358 # call to a security-critical function can be just as important
4359 # as adding or changing the arguments.
4360 if line.startswith('-') or (line.startswith('+')
4361 and not line.startswith('++')):
4362 for name, pattern in _PATTERNS_TO_CHECK.items():
4363 if pattern.search(line):
4364 path = f.LocalPath()
4365 if not path in files_to_functions:
4366 files_to_functions[path] = set()
4367 files_to_functions[path].add(name)
4368 return files_to_functions
4369
4370
4371def CheckSecurityChanges(input_api, output_api):
4372 """Checks that changes involving security-critical functions are reviewed
4373 by the security team.
4374 """
4375 files_to_functions = _GetFilesUsingSecurityCriticalFunctions(input_api)
4376 if not len(files_to_functions):
4377 return []
4378
Sam Maiera6e76d72022-02-11 21:43:504379 owners_file = 'ipc/SECURITY_OWNERS'
Daniel Chenga37c03db2022-05-12 17:20:344380 if _ChangeHasSecurityReviewer(input_api, owners_file):
Sam Maiera6e76d72022-02-11 21:43:504381 return []
4382
Daniel Chenga37c03db2022-05-12 17:20:344383 msg = 'The following files change calls to security-sensitive functions\n' \
Sam Maiera6e76d72022-02-11 21:43:504384 'that need to be reviewed by {}.\n'.format(owners_file)
4385 for path, names in files_to_functions.items():
4386 msg += ' {}\n'.format(path)
4387 for name in names:
4388 msg += ' {}\n'.format(name)
4389 msg += '\n'
4390
4391 if input_api.is_committing:
4392 output = output_api.PresubmitError
Mohamed Heikale217fc852020-07-06 19:44:034393 else:
Sam Maiera6e76d72022-02-11 21:43:504394 output = output_api.PresubmitNotifyResult
4395 return [output(msg)]
4396
4397
4398def CheckSetNoParent(input_api, output_api):
4399 """Checks that set noparent is only used together with an OWNERS file in
4400 //build/OWNERS.setnoparent (see also
4401 //docs/code_reviews.md#owners-files-details)
4402 """
4403 # Return early if no OWNERS files were modified.
4404 if not any(f.LocalPath().endswith('OWNERS')
4405 for f in input_api.AffectedFiles(include_deletes=False)):
4406 return []
4407
4408 errors = []
4409
4410 allowed_owners_files_file = 'build/OWNERS.setnoparent'
4411 allowed_owners_files = set()
Bruce Dawson58a45d22023-02-27 11:24:164412 with open(allowed_owners_files_file, 'r', encoding='utf-8') as f:
Sam Maiera6e76d72022-02-11 21:43:504413 for line in f:
4414 line = line.strip()
4415 if not line or line.startswith('#'):
4416 continue
4417 allowed_owners_files.add(line)
4418
4419 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
4420
4421 for f in input_api.AffectedFiles(include_deletes=False):
4422 if not f.LocalPath().endswith('OWNERS'):
4423 continue
4424
4425 found_owners_files = set()
4426 found_set_noparent_lines = dict()
4427
4428 # Parse the OWNERS file.
4429 for lineno, line in enumerate(f.NewContents(), 1):
4430 line = line.strip()
4431 if line.startswith('set noparent'):
4432 found_set_noparent_lines[''] = lineno
4433 if line.startswith('file://'):
4434 if line in allowed_owners_files:
4435 found_owners_files.add('')
4436 if line.startswith('per-file'):
4437 match = per_file_pattern.match(line)
4438 if match:
4439 glob = match.group(1).strip()
4440 directive = match.group(2).strip()
4441 if directive == 'set noparent':
4442 found_set_noparent_lines[glob] = lineno
4443 if directive.startswith('file://'):
4444 if directive in allowed_owners_files:
4445 found_owners_files.add(glob)
4446
4447 # Check that every set noparent line has a corresponding file:// line
4448 # listed in build/OWNERS.setnoparent. An exception is made for top level
4449 # directories since src/OWNERS shouldn't review them.
Bruce Dawson6bb0d672022-04-06 15:13:494450 linux_path = f.LocalPath().replace(input_api.os_path.sep, '/')
4451 if (linux_path.count('/') != 1
4452 and (not linux_path in _EXCLUDED_SET_NO_PARENT_PATHS)):
Sam Maiera6e76d72022-02-11 21:43:504453 for set_noparent_line in found_set_noparent_lines:
4454 if set_noparent_line in found_owners_files:
4455 continue
4456 errors.append(' %s:%d' %
Bruce Dawson6bb0d672022-04-06 15:13:494457 (linux_path,
Sam Maiera6e76d72022-02-11 21:43:504458 found_set_noparent_lines[set_noparent_line]))
4459
4460 results = []
4461 if errors:
4462 if input_api.is_committing:
4463 output = output_api.PresubmitError
4464 else:
4465 output = output_api.PresubmitPromptWarning
4466 results.append(
4467 output(
4468 'Found the following "set noparent" restrictions in OWNERS files that '
4469 'do not include owners from build/OWNERS.setnoparent:',
4470 long_text='\n\n'.join(errors)))
4471 return results
4472
4473
4474def CheckUselessForwardDeclarations(input_api, output_api):
4475 """Checks that added or removed lines in non third party affected
4476 header files do not lead to new useless class or struct forward
4477 declaration.
4478 """
4479 results = []
4480 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
4481 input_api.re.MULTILINE)
4482 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
4483 input_api.re.MULTILINE)
4484 for f in input_api.AffectedFiles(include_deletes=False):
4485 if (f.LocalPath().startswith('third_party')
4486 and not f.LocalPath().startswith('third_party/blink')
4487 and not f.LocalPath().startswith('third_party\\blink')):
4488 continue
4489
4490 if not f.LocalPath().endswith('.h'):
4491 continue
4492
4493 contents = input_api.ReadFile(f)
4494 fwd_decls = input_api.re.findall(class_pattern, contents)
4495 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
4496
4497 useless_fwd_decls = []
4498 for decl in fwd_decls:
4499 count = sum(1 for _ in input_api.re.finditer(
4500 r'\b%s\b' % input_api.re.escape(decl), contents))
4501 if count == 1:
4502 useless_fwd_decls.append(decl)
4503
4504 if not useless_fwd_decls:
4505 continue
4506
4507 for line in f.GenerateScmDiff().splitlines():
4508 if (line.startswith('-') and not line.startswith('--')
4509 or line.startswith('+') and not line.startswith('++')):
4510 for decl in useless_fwd_decls:
4511 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
4512 results.append(
4513 output_api.PresubmitPromptWarning(
4514 '%s: %s forward declaration is no longer needed'
4515 % (f.LocalPath(), decl)))
4516 useless_fwd_decls.remove(decl)
4517
4518 return results
4519
4520
4521def _CheckAndroidDebuggableBuild(input_api, output_api):
4522 """Checks that code uses BuildInfo.isDebugAndroid() instead of
4523 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
4524 this is a debuggable build of Android.
4525 """
4526 build_type_check_pattern = input_api.re.compile(
4527 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
4528
4529 errors = []
4530
4531 sources = lambda affected_file: input_api.FilterSourceFile(
4532 affected_file,
4533 files_to_skip=(
4534 _EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
4535 DEFAULT_FILES_TO_SKIP + (
Bruce Dawson40fece62022-09-16 19:58:314536 r"^android_webview/support_library/boundary_interfaces/",
4537 r"^chrome/android/webapk/.*",
4538 r'^third_party/.*',
4539 r"tools/android/customtabs_benchmark/.*",
4540 r"webview/chromium/License.*",
Sam Maiera6e76d72022-02-11 21:43:504541 )),
4542 files_to_check=[r'.*\.java$'])
4543
4544 for f in input_api.AffectedSourceFiles(sources):
4545 for line_num, line in f.ChangedContents():
4546 if build_type_check_pattern.search(line):
4547 errors.append("%s:%d" % (f.LocalPath(), line_num))
4548
4549 results = []
4550
4551 if errors:
4552 results.append(
4553 output_api.PresubmitPromptWarning(
4554 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
4555 ' Please use BuildInfo.isDebugAndroid() instead.', errors))
4556
4557 return results
4558
4559# TODO: add unit tests
4560def _CheckAndroidToastUsage(input_api, output_api):
4561 """Checks that code uses org.chromium.ui.widget.Toast instead of
4562 android.widget.Toast (Chromium Toast doesn't force hardware
4563 acceleration on low-end devices, saving memory).
4564 """
4565 toast_import_pattern = input_api.re.compile(
4566 r'^import android\.widget\.Toast;$')
4567
4568 errors = []
4569
4570 sources = lambda affected_file: input_api.FilterSourceFile(
4571 affected_file,
4572 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
Bruce Dawson40fece62022-09-16 19:58:314573 DEFAULT_FILES_TO_SKIP + (r'^chromecast/.*',
4574 r'^remoting/.*')),
Sam Maiera6e76d72022-02-11 21:43:504575 files_to_check=[r'.*\.java$'])
4576
4577 for f in input_api.AffectedSourceFiles(sources):
4578 for line_num, line in f.ChangedContents():
4579 if toast_import_pattern.search(line):
4580 errors.append("%s:%d" % (f.LocalPath(), line_num))
4581
4582 results = []
4583
4584 if errors:
4585 results.append(
4586 output_api.PresubmitError(
4587 'android.widget.Toast usage is detected. Android toasts use hardware'
4588 ' acceleration, and can be\ncostly on low-end devices. Please use'
4589 ' org.chromium.ui.widget.Toast instead.\n'
4590 'Contact [email protected] if you have any questions.',
4591 errors))
4592
4593 return results
4594
4595
4596def _CheckAndroidCrLogUsage(input_api, output_api):
4597 """Checks that new logs using org.chromium.base.Log:
4598 - Are using 'TAG' as variable name for the tags (warn)
4599 - Are using a tag that is shorter than 20 characters (error)
4600 """
4601
4602 # Do not check format of logs in the given files
4603 cr_log_check_excluded_paths = [
4604 # //chrome/android/webapk cannot depend on //base
Bruce Dawson40fece62022-09-16 19:58:314605 r"^chrome/android/webapk/.*",
Sam Maiera6e76d72022-02-11 21:43:504606 # WebView license viewer code cannot depend on //base; used in stub APK.
Bruce Dawson40fece62022-09-16 19:58:314607 r"^android_webview/glue/java/src/com/android/"
4608 r"webview/chromium/License.*",
Sam Maiera6e76d72022-02-11 21:43:504609 # The customtabs_benchmark is a small app that does not depend on Chromium
4610 # java pieces.
Bruce Dawson40fece62022-09-16 19:58:314611 r"tools/android/customtabs_benchmark/.*",
Sam Maiera6e76d72022-02-11 21:43:504612 ]
4613
4614 cr_log_import_pattern = input_api.re.compile(
4615 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
4616 class_in_base_pattern = input_api.re.compile(
4617 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
4618 has_some_log_import_pattern = input_api.re.compile(r'^import .*\.Log;$',
4619 input_api.re.MULTILINE)
4620 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
4621 log_call_pattern = input_api.re.compile(r'\bLog\.\w\((?P<tag>\"?\w+)')
4622 log_decl_pattern = input_api.re.compile(
4623 r'static final String TAG = "(?P<name>(.*))"')
4624 rough_log_decl_pattern = input_api.re.compile(r'\bString TAG\s*=')
4625
4626 REF_MSG = ('See docs/android_logging.md for more info.')
4627 sources = lambda x: input_api.FilterSourceFile(
4628 x,
4629 files_to_check=[r'.*\.java$'],
4630 files_to_skip=cr_log_check_excluded_paths)
4631
4632 tag_decl_errors = []
Andrew Grieved3a35d82024-01-02 21:24:384633 tag_length_errors = []
Sam Maiera6e76d72022-02-11 21:43:504634 tag_errors = []
4635 tag_with_dot_errors = []
4636 util_log_errors = []
4637
4638 for f in input_api.AffectedSourceFiles(sources):
4639 file_content = input_api.ReadFile(f)
4640 has_modified_logs = False
4641 # Per line checks
4642 if (cr_log_import_pattern.search(file_content)
4643 or (class_in_base_pattern.search(file_content)
4644 and not has_some_log_import_pattern.search(file_content))):
4645 # Checks to run for files using cr log
4646 for line_num, line in f.ChangedContents():
4647 if rough_log_decl_pattern.search(line):
4648 has_modified_logs = True
4649
4650 # Check if the new line is doing some logging
4651 match = log_call_pattern.search(line)
4652 if match:
4653 has_modified_logs = True
4654
4655 # Make sure it uses "TAG"
4656 if not match.group('tag') == 'TAG':
4657 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
4658 else:
4659 # Report non cr Log function calls in changed lines
4660 for line_num, line in f.ChangedContents():
4661 if log_call_pattern.search(line):
4662 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
4663
4664 # Per file checks
4665 if has_modified_logs:
4666 # Make sure the tag is using the "cr" prefix and is not too long
4667 match = log_decl_pattern.search(file_content)
4668 tag_name = match.group('name') if match else None
4669 if not tag_name:
4670 tag_decl_errors.append(f.LocalPath())
Andrew Grieved3a35d82024-01-02 21:24:384671 elif len(tag_name) > 20:
4672 tag_length_errors.append(f.LocalPath())
Sam Maiera6e76d72022-02-11 21:43:504673 elif '.' in tag_name:
4674 tag_with_dot_errors.append(f.LocalPath())
4675
4676 results = []
4677 if tag_decl_errors:
4678 results.append(
4679 output_api.PresubmitPromptWarning(
4680 'Please define your tags using the suggested format: .\n'
4681 '"private static final String TAG = "<package tag>".\n'
4682 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
4683 tag_decl_errors))
4684
Andrew Grieved3a35d82024-01-02 21:24:384685 if tag_length_errors:
4686 results.append(
4687 output_api.PresubmitError(
4688 'The tag length is restricted by the system to be at most '
4689 '20 characters.\n' + REF_MSG, tag_length_errors))
4690
Sam Maiera6e76d72022-02-11 21:43:504691 if tag_errors:
4692 results.append(
4693 output_api.PresubmitPromptWarning(
4694 'Please use a variable named "TAG" for your log tags.\n' +
4695 REF_MSG, tag_errors))
4696
4697 if util_log_errors:
4698 results.append(
4699 output_api.PresubmitPromptWarning(
4700 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
4701 util_log_errors))
4702
4703 if tag_with_dot_errors:
4704 results.append(
4705 output_api.PresubmitPromptWarning(
4706 'Dot in log tags cause them to be elided in crash reports.\n' +
4707 REF_MSG, tag_with_dot_errors))
4708
4709 return results
4710
4711
Sam Maiera6e76d72022-02-11 21:43:504712def _CheckAndroidTestAnnotationUsage(input_api, output_api):
4713 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
4714 deprecated_annotation_import_pattern = input_api.re.compile(
4715 r'^import android\.test\.suitebuilder\.annotation\..*;',
4716 input_api.re.MULTILINE)
4717 sources = lambda x: input_api.FilterSourceFile(
4718 x, files_to_check=[r'.*\.java$'], files_to_skip=None)
4719 errors = []
4720 for f in input_api.AffectedFiles(file_filter=sources):
4721 for line_num, line in f.ChangedContents():
4722 if deprecated_annotation_import_pattern.search(line):
4723 errors.append("%s:%d" % (f.LocalPath(), line_num))
4724
4725 results = []
4726 if errors:
4727 results.append(
4728 output_api.PresubmitError(
4729 'Annotations in android.test.suitebuilder.annotation have been'
Mohamed Heikal3d7a94c2023-03-28 16:55:244730 ' deprecated since API level 24. Please use androidx.test.filters'
4731 ' from //third_party/androidx:androidx_test_runner_java instead.'
Sam Maiera6e76d72022-02-11 21:43:504732 ' Contact [email protected] if you have any questions.',
4733 errors))
4734 return results
4735
4736
4737def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
4738 """Checks if MDPI assets are placed in a correct directory."""
Bruce Dawson6c05e852022-07-21 15:48:514739 file_filter = lambda f: (f.LocalPath().endswith(
4740 '.png') and ('/res/drawable/'.replace('/', input_api.os_path.sep) in f.
4741 LocalPath() or '/res/drawable-ldrtl/'.replace(
4742 '/', input_api.os_path.sep) in f.LocalPath()))
Sam Maiera6e76d72022-02-11 21:43:504743 errors = []
4744 for f in input_api.AffectedFiles(include_deletes=False,
4745 file_filter=file_filter):
4746 errors.append(' %s' % f.LocalPath())
4747
4748 results = []
4749 if errors:
4750 results.append(
4751 output_api.PresubmitError(
4752 'MDPI assets should be placed in /res/drawable-mdpi/ or '
4753 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
4754 '/res/drawable-ldrtl/.\n'
4755 'Contact [email protected] if you have questions.', errors))
4756 return results
4757
4758
4759def _CheckAndroidWebkitImports(input_api, output_api):
4760 """Checks that code uses org.chromium.base.Callback instead of
4761 android.webview.ValueCallback except in the WebView glue layer
4762 and WebLayer.
4763 """
4764 valuecallback_import_pattern = input_api.re.compile(
4765 r'^import android\.webkit\.ValueCallback;$')
4766
4767 errors = []
4768
4769 sources = lambda affected_file: input_api.FilterSourceFile(
4770 affected_file,
4771 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
4772 DEFAULT_FILES_TO_SKIP + (
Bruce Dawson40fece62022-09-16 19:58:314773 r'^android_webview/glue/.*',
4774 r'^weblayer/.*',
Sam Maiera6e76d72022-02-11 21:43:504775 )),
4776 files_to_check=[r'.*\.java$'])
4777
4778 for f in input_api.AffectedSourceFiles(sources):
4779 for line_num, line in f.ChangedContents():
4780 if valuecallback_import_pattern.search(line):
4781 errors.append("%s:%d" % (f.LocalPath(), line_num))
4782
4783 results = []
4784
4785 if errors:
4786 results.append(
4787 output_api.PresubmitError(
4788 'android.webkit.ValueCallback usage is detected outside of the glue'
4789 ' layer. To stay compatible with the support library, android.webkit.*'
4790 ' classes should only be used inside the glue layer and'
4791 ' org.chromium.base.Callback should be used instead.', errors))
4792
4793 return results
4794
4795
4796def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
4797 """Checks Android XML styles """
4798
4799 # Return early if no relevant files were modified.
4800 if not any(
4801 _IsXmlOrGrdFile(input_api, f.LocalPath())
4802 for f in input_api.AffectedFiles(include_deletes=False)):
4803 return []
4804
4805 import sys
4806 original_sys_path = sys.path
4807 try:
4808 sys.path = sys.path + [
4809 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
4810 'android', 'checkxmlstyle')
4811 ]
4812 import checkxmlstyle
4813 finally:
4814 # Restore sys.path to what it was before.
4815 sys.path = original_sys_path
4816
4817 if is_check_on_upload:
4818 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
4819 else:
4820 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
4821
4822
4823def _CheckAndroidInfoBarDeprecation(input_api, output_api):
4824 """Checks Android Infobar Deprecation """
4825
4826 import sys
4827 original_sys_path = sys.path
4828 try:
4829 sys.path = sys.path + [
4830 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
4831 'android', 'infobar_deprecation')
4832 ]
4833 import infobar_deprecation
4834 finally:
4835 # Restore sys.path to what it was before.
4836 sys.path = original_sys_path
4837
4838 return infobar_deprecation.CheckDeprecationOnUpload(input_api, output_api)
4839
4840
4841class _PydepsCheckerResult:
4842 def __init__(self, cmd, pydeps_path, process, old_contents):
4843 self._cmd = cmd
4844 self._pydeps_path = pydeps_path
4845 self._process = process
4846 self._old_contents = old_contents
4847
4848 def GetError(self):
4849 """Returns an error message, or None."""
4850 import difflib
Andrew Grieved27620b62023-07-13 16:35:074851 new_contents = self._process.stdout.read().splitlines()[2:]
Sam Maiera6e76d72022-02-11 21:43:504852 if self._process.wait() != 0:
4853 # STDERR should already be printed.
4854 return 'Command failed: ' + self._cmd
Sam Maiera6e76d72022-02-11 21:43:504855 if self._old_contents != new_contents:
4856 diff = '\n'.join(
4857 difflib.context_diff(self._old_contents, new_contents))
4858 return ('File is stale: {}\n'
4859 'Diff (apply to fix):\n'
4860 '{}\n'
4861 'To regenerate, run:\n\n'
4862 ' {}').format(self._pydeps_path, diff, self._cmd)
4863 return None
4864
4865
4866class PydepsChecker:
4867 def __init__(self, input_api, pydeps_files):
4868 self._file_cache = {}
4869 self._input_api = input_api
4870 self._pydeps_files = pydeps_files
4871
4872 def _LoadFile(self, path):
4873 """Returns the list of paths within a .pydeps file relative to //."""
4874 if path not in self._file_cache:
4875 with open(path, encoding='utf-8') as f:
4876 self._file_cache[path] = f.read()
4877 return self._file_cache[path]
4878
4879 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
Gao Shenga79ebd42022-08-08 17:25:594880 """Returns an iterable of paths within the .pydep, relativized to //."""
Sam Maiera6e76d72022-02-11 21:43:504881 pydeps_data = self._LoadFile(pydeps_path)
4882 uses_gn_paths = '--gn-paths' in pydeps_data
4883 entries = (l for l in pydeps_data.splitlines()
4884 if not l.startswith('#'))
4885 if uses_gn_paths:
4886 # Paths look like: //foo/bar/baz
4887 return (e[2:] for e in entries)
4888 else:
4889 # Paths look like: path/relative/to/file.pydeps
4890 os_path = self._input_api.os_path
4891 pydeps_dir = os_path.dirname(pydeps_path)
4892 return (os_path.normpath(os_path.join(pydeps_dir, e))
4893 for e in entries)
4894
4895 def _CreateFilesToPydepsMap(self):
4896 """Returns a map of local_path -> list_of_pydeps."""
4897 ret = {}
4898 for pydep_local_path in self._pydeps_files:
4899 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
4900 ret.setdefault(path, []).append(pydep_local_path)
4901 return ret
4902
4903 def ComputeAffectedPydeps(self):
4904 """Returns an iterable of .pydeps files that might need regenerating."""
4905 affected_pydeps = set()
4906 file_to_pydeps_map = None
4907 for f in self._input_api.AffectedFiles(include_deletes=True):
4908 local_path = f.LocalPath()
4909 # Changes to DEPS can lead to .pydeps changes if any .py files are in
4910 # subrepositories. We can't figure out which files change, so re-check
4911 # all files.
4912 # Changes to print_python_deps.py affect all .pydeps.
4913 if local_path in ('DEPS', 'PRESUBMIT.py'
4914 ) or local_path.endswith('print_python_deps.py'):
4915 return self._pydeps_files
4916 elif local_path.endswith('.pydeps'):
4917 if local_path in self._pydeps_files:
4918 affected_pydeps.add(local_path)
4919 elif local_path.endswith('.py'):
4920 if file_to_pydeps_map is None:
4921 file_to_pydeps_map = self._CreateFilesToPydepsMap()
4922 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
4923 return affected_pydeps
4924
4925 def DetermineIfStaleAsync(self, pydeps_path):
4926 """Runs print_python_deps.py to see if the files is stale."""
4927 import os
4928
4929 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
4930 if old_pydeps_data:
4931 cmd = old_pydeps_data[1][1:].strip()
4932 if '--output' not in cmd:
4933 cmd += ' --output ' + pydeps_path
4934 old_contents = old_pydeps_data[2:]
4935 else:
4936 # A default cmd that should work in most cases (as long as pydeps filename
4937 # matches the script name) so that PRESUBMIT.py does not crash if pydeps
4938 # file is empty/new.
4939 cmd = 'build/print_python_deps.py {} --root={} --output={}'.format(
4940 pydeps_path[:-4], os.path.dirname(pydeps_path), pydeps_path)
4941 old_contents = []
4942 env = dict(os.environ)
4943 env['PYTHONDONTWRITEBYTECODE'] = '1'
4944 process = self._input_api.subprocess.Popen(
4945 cmd + ' --output ""',
4946 shell=True,
4947 env=env,
4948 stdout=self._input_api.subprocess.PIPE,
4949 encoding='utf-8')
4950 return _PydepsCheckerResult(cmd, pydeps_path, process, old_contents)
agrievef32bcc72016-04-04 14:57:404951
4952
Tibor Goldschwendt360793f72019-06-25 18:23:494953def _ParseGclientArgs():
Sam Maiera6e76d72022-02-11 21:43:504954 args = {}
4955 with open('build/config/gclient_args.gni', 'r') as f:
4956 for line in f:
4957 line = line.strip()
4958 if not line or line.startswith('#'):
4959 continue
4960 attribute, value = line.split('=')
4961 args[attribute.strip()] = value.strip()
4962 return args
Tibor Goldschwendt360793f72019-06-25 18:23:494963
4964
Saagar Sanghavifceeaae2020-08-12 16:40:364965def CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
Sam Maiera6e76d72022-02-11 21:43:504966 """Checks if a .pydeps file needs to be regenerated."""
4967 # This check is for Python dependency lists (.pydeps files), and involves
4968 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
4969 # doesn't work on Windows and Mac, so skip it on other platforms.
4970 if not input_api.platform.startswith('linux'):
4971 return []
Erik Staabc734cd7a2021-11-23 03:11:524972
Sam Maiera6e76d72022-02-11 21:43:504973 results = []
4974 # First, check for new / deleted .pydeps.
4975 for f in input_api.AffectedFiles(include_deletes=True):
4976 # Check whether we are running the presubmit check for a file in src.
4977 # f.LocalPath is relative to repo (src, or internal repo).
4978 # os_path.exists is relative to src repo.
4979 # Therefore if os_path.exists is true, it means f.LocalPath is relative
4980 # to src and we can conclude that the pydeps is in src.
4981 if f.LocalPath().endswith('.pydeps'):
4982 if input_api.os_path.exists(f.LocalPath()):
4983 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
4984 results.append(
4985 output_api.PresubmitError(
4986 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
4987 'remove %s' % f.LocalPath()))
4988 elif f.Action() != 'D' and f.LocalPath(
4989 ) not in _ALL_PYDEPS_FILES:
4990 results.append(
4991 output_api.PresubmitError(
4992 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
4993 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:404994
Sam Maiera6e76d72022-02-11 21:43:504995 if results:
4996 return results
4997
4998 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
4999 checker = checker_for_tests or PydepsChecker(input_api, _ALL_PYDEPS_FILES)
5000 affected_pydeps = set(checker.ComputeAffectedPydeps())
5001 affected_android_pydeps = affected_pydeps.intersection(
5002 set(_ANDROID_SPECIFIC_PYDEPS_FILES))
5003 if affected_android_pydeps and not is_android:
5004 results.append(
5005 output_api.PresubmitPromptOrNotify(
5006 'You have changed python files that may affect pydeps for android\n'
Gao Shenga79ebd42022-08-08 17:25:595007 'specific scripts. However, the relevant presubmit check cannot be\n'
Sam Maiera6e76d72022-02-11 21:43:505008 'run because you are not using an Android checkout. To validate that\n'
5009 'the .pydeps are correct, re-run presubmit in an Android checkout, or\n'
5010 'use the android-internal-presubmit optional trybot.\n'
5011 'Possibly stale pydeps files:\n{}'.format(
5012 '\n'.join(affected_android_pydeps))))
5013
5014 all_pydeps = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
5015 pydeps_to_check = affected_pydeps.intersection(all_pydeps)
5016 # Process these concurrently, as each one takes 1-2 seconds.
5017 pydep_results = [checker.DetermineIfStaleAsync(p) for p in pydeps_to_check]
5018 for result in pydep_results:
5019 error_msg = result.GetError()
5020 if error_msg:
5021 results.append(output_api.PresubmitError(error_msg))
5022
agrievef32bcc72016-04-04 14:57:405023 return results
5024
agrievef32bcc72016-04-04 14:57:405025
Saagar Sanghavifceeaae2020-08-12 16:40:365026def CheckSingletonInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505027 """Checks to make sure no header files have |Singleton<|."""
5028
5029 def FileFilter(affected_file):
5030 # It's ok for base/memory/singleton.h to have |Singleton<|.
5031 files_to_skip = (_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP +
Bruce Dawson40fece62022-09-16 19:58:315032 (r"^base/memory/singleton\.h$",
5033 r"^net/quic/platform/impl/quic_singleton_impl\.h$"))
Sam Maiera6e76d72022-02-11 21:43:505034 return input_api.FilterSourceFile(affected_file,
5035 files_to_skip=files_to_skip)
glidere61efad2015-02-18 17:39:435036
Sam Maiera6e76d72022-02-11 21:43:505037 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
5038 files = []
5039 for f in input_api.AffectedSourceFiles(FileFilter):
5040 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx')
5041 or f.LocalPath().endswith('.hpp')
5042 or f.LocalPath().endswith('.inl')):
5043 contents = input_api.ReadFile(f)
5044 for line in contents.splitlines(False):
5045 if (not line.lstrip().startswith('//')
5046 and # Strip C++ comment.
5047 pattern.search(line)):
5048 files.append(f)
5049 break
glidere61efad2015-02-18 17:39:435050
Sam Maiera6e76d72022-02-11 21:43:505051 if files:
5052 return [
5053 output_api.PresubmitError(
5054 'Found base::Singleton<T> in the following header files.\n' +
5055 'Please move them to an appropriate source file so that the ' +
5056 'template gets instantiated in a single compilation unit.',
5057 files)
5058 ]
5059 return []
glidere61efad2015-02-18 17:39:435060
5061
[email protected]fd20b902014-05-09 02:14:535062_DEPRECATED_CSS = [
5063 # Values
5064 ( "-webkit-box", "flex" ),
5065 ( "-webkit-inline-box", "inline-flex" ),
5066 ( "-webkit-flex", "flex" ),
5067 ( "-webkit-inline-flex", "inline-flex" ),
5068 ( "-webkit-min-content", "min-content" ),
5069 ( "-webkit-max-content", "max-content" ),
5070
5071 # Properties
5072 ( "-webkit-background-clip", "background-clip" ),
5073 ( "-webkit-background-origin", "background-origin" ),
5074 ( "-webkit-background-size", "background-size" ),
5075 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:445076 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:535077
5078 # Functions
5079 ( "-webkit-gradient", "gradient" ),
5080 ( "-webkit-repeating-gradient", "repeating-gradient" ),
5081 ( "-webkit-linear-gradient", "linear-gradient" ),
5082 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
5083 ( "-webkit-radial-gradient", "radial-gradient" ),
5084 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
5085]
5086
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:205087
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:495088# TODO: add unit tests
Saagar Sanghavifceeaae2020-08-12 16:40:365089def CheckNoDeprecatedCss(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505090 """ Make sure that we don't use deprecated CSS
5091 properties, functions or values. Our external
5092 documentation and iOS CSS for dom distiller
5093 (reader mode) are ignored by the hooks as it
5094 needs to be consumed by WebKit. """
5095 results = []
5096 file_inclusion_pattern = [r".+\.css$"]
5097 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
5098 input_api.DEFAULT_FILES_TO_SKIP +
5099 (r"^chrome/common/extensions/docs", r"^chrome/docs",
Teresa Mao1d910882024-04-26 21:06:255100 r"^native_client_sdk",
5101 # The NTP team prefers reserving -webkit-line-clamp for
5102 # ellipsis effect which can only be used with -webkit-box.
5103 r"ui/webui/resources/cr_components/most_visited/.*\.css$"))
Sam Maiera6e76d72022-02-11 21:43:505104 file_filter = lambda f: input_api.FilterSourceFile(
5105 f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
5106 for fpath in input_api.AffectedFiles(file_filter=file_filter):
5107 for line_num, line in fpath.ChangedContents():
5108 for (deprecated_value, value) in _DEPRECATED_CSS:
5109 if deprecated_value in line:
5110 results.append(
5111 output_api.PresubmitError(
5112 "%s:%d: Use of deprecated CSS %s, use %s instead" %
5113 (fpath.LocalPath(), line_num, deprecated_value,
5114 value)))
5115 return results
[email protected]fd20b902014-05-09 02:14:535116
mohan.reddyf21db962014-10-16 12:26:475117
Saagar Sanghavifceeaae2020-08-12 16:40:365118def CheckForRelativeIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505119 bad_files = {}
5120 for f in input_api.AffectedFiles(include_deletes=False):
5121 if (f.LocalPath().startswith('third_party')
5122 and not f.LocalPath().startswith('third_party/blink')
5123 and not f.LocalPath().startswith('third_party\\blink')):
5124 continue
rlanday6802cf632017-05-30 17:48:365125
Sam Maiera6e76d72022-02-11 21:43:505126 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
5127 continue
rlanday6802cf632017-05-30 17:48:365128
Sam Maiera6e76d72022-02-11 21:43:505129 relative_includes = [
5130 line for _, line in f.ChangedContents()
5131 if "#include" in line and "../" in line
5132 ]
5133 if not relative_includes:
5134 continue
5135 bad_files[f.LocalPath()] = relative_includes
rlanday6802cf632017-05-30 17:48:365136
Sam Maiera6e76d72022-02-11 21:43:505137 if not bad_files:
5138 return []
rlanday6802cf632017-05-30 17:48:365139
Sam Maiera6e76d72022-02-11 21:43:505140 error_descriptions = []
5141 for file_path, bad_lines in bad_files.items():
5142 error_description = file_path
5143 for line in bad_lines:
5144 error_description += '\n ' + line
5145 error_descriptions.append(error_description)
rlanday6802cf632017-05-30 17:48:365146
Sam Maiera6e76d72022-02-11 21:43:505147 results = []
5148 results.append(
5149 output_api.PresubmitError(
5150 'You added one or more relative #include paths (including "../").\n'
5151 'These shouldn\'t be used because they can be used to include headers\n'
5152 'from code that\'s not correctly specified as a dependency in the\n'
5153 'relevant BUILD.gn file(s).', error_descriptions))
rlanday6802cf632017-05-30 17:48:365154
Sam Maiera6e76d72022-02-11 21:43:505155 return results
rlanday6802cf632017-05-30 17:48:365156
Takeshi Yoshinoe387aa32017-08-02 13:16:135157
Saagar Sanghavifceeaae2020-08-12 16:40:365158def CheckForCcIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505159 """Check that nobody tries to include a cc file. It's a relatively
5160 common error which results in duplicate symbols in object
5161 files. This may not always break the build until someone later gets
5162 very confusing linking errors."""
5163 results = []
5164 for f in input_api.AffectedFiles(include_deletes=False):
5165 # We let third_party code do whatever it wants
5166 if (f.LocalPath().startswith('third_party')
5167 and not f.LocalPath().startswith('third_party/blink')
5168 and not f.LocalPath().startswith('third_party\\blink')):
5169 continue
Daniel Bratell65b033262019-04-23 08:17:065170
Sam Maiera6e76d72022-02-11 21:43:505171 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
5172 continue
Daniel Bratell65b033262019-04-23 08:17:065173
Sam Maiera6e76d72022-02-11 21:43:505174 for _, line in f.ChangedContents():
5175 if line.startswith('#include "'):
5176 included_file = line.split('"')[1]
5177 if _IsCPlusPlusFile(input_api, included_file):
5178 # The most common naming for external files with C++ code,
5179 # apart from standard headers, is to call them foo.inc, but
5180 # Chromium sometimes uses foo-inc.cc so allow that as well.
5181 if not included_file.endswith(('.h', '-inc.cc')):
5182 results.append(
5183 output_api.PresubmitError(
5184 'Only header files or .inc files should be included in other\n'
5185 'C++ files. Compiling the contents of a cc file more than once\n'
5186 'will cause duplicate information in the build which may later\n'
5187 'result in strange link_errors.\n' +
5188 f.LocalPath() + ':\n ' + line))
Daniel Bratell65b033262019-04-23 08:17:065189
Sam Maiera6e76d72022-02-11 21:43:505190 return results
Daniel Bratell65b033262019-04-23 08:17:065191
5192
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205193def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
Sam Maiera6e76d72022-02-11 21:43:505194 if not isinstance(key, ast.Str):
5195 return 'Key at line %d must be a string literal' % key.lineno
5196 if not isinstance(value, ast.Dict):
5197 return 'Value at line %d must be a dict' % value.lineno
5198 if len(value.keys) != 1:
5199 return 'Dict at line %d must have single entry' % value.lineno
5200 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
5201 return (
5202 'Entry at line %d must have a string literal \'filepath\' as key' %
5203 value.lineno)
5204 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:135205
Takeshi Yoshinoe387aa32017-08-02 13:16:135206
Sergey Ulanov4af16052018-11-08 02:41:465207def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Sam Maiera6e76d72022-02-11 21:43:505208 if not isinstance(key, ast.Str):
5209 return 'Key at line %d must be a string literal' % key.lineno
5210 if not isinstance(value, ast.List):
5211 return 'Value at line %d must be a list' % value.lineno
5212 for element in value.elts:
5213 if not isinstance(element, ast.Str):
5214 return 'Watchlist elements on line %d is not a string' % key.lineno
5215 if not email_regex.match(element.s):
5216 return ('Watchlist element on line %d doesn\'t look like a valid '
5217 + 'email: %s') % (key.lineno, element.s)
5218 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:135219
Takeshi Yoshinoe387aa32017-08-02 13:16:135220
Sergey Ulanov4af16052018-11-08 02:41:465221def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Sam Maiera6e76d72022-02-11 21:43:505222 mismatch_template = (
5223 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
5224 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:135225
Sam Maiera6e76d72022-02-11 21:43:505226 email_regex = input_api.re.compile(
5227 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
Sergey Ulanov4af16052018-11-08 02:41:465228
Sam Maiera6e76d72022-02-11 21:43:505229 ast = input_api.ast
5230 i = 0
5231 last_key = ''
5232 while True:
5233 if i >= len(wd_dict.keys):
5234 if i >= len(w_dict.keys):
5235 return None
5236 return mismatch_template % ('missing',
5237 'line %d' % w_dict.keys[i].lineno)
5238 elif i >= len(w_dict.keys):
5239 return (mismatch_template %
5240 ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:135241
Sam Maiera6e76d72022-02-11 21:43:505242 wd_key = wd_dict.keys[i]
5243 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:135244
Sam Maiera6e76d72022-02-11 21:43:505245 result = _CheckWatchlistDefinitionsEntrySyntax(wd_key,
5246 wd_dict.values[i], ast)
5247 if result is not None:
5248 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:135249
Sam Maiera6e76d72022-02-11 21:43:505250 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast,
5251 email_regex)
5252 if result is not None:
5253 return 'Bad entry in WATCHLISTS dict: %s' % result
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205254
Sam Maiera6e76d72022-02-11 21:43:505255 if wd_key.s != w_key.s:
5256 return mismatch_template % ('%s at line %d' %
5257 (wd_key.s, wd_key.lineno),
5258 '%s at line %d' %
5259 (w_key.s, w_key.lineno))
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205260
Sam Maiera6e76d72022-02-11 21:43:505261 if wd_key.s < last_key:
5262 return (
5263 'WATCHLISTS dict is not sorted lexicographically at line %d and %d'
5264 % (wd_key.lineno, w_key.lineno))
5265 last_key = wd_key.s
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205266
Sam Maiera6e76d72022-02-11 21:43:505267 i = i + 1
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205268
5269
Sergey Ulanov4af16052018-11-08 02:41:465270def _CheckWATCHLISTSSyntax(expression, input_api):
Sam Maiera6e76d72022-02-11 21:43:505271 ast = input_api.ast
5272 if not isinstance(expression, ast.Expression):
5273 return 'WATCHLISTS file must contain a valid expression'
5274 dictionary = expression.body
5275 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
5276 return 'WATCHLISTS file must have single dict with exactly two entries'
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205277
Sam Maiera6e76d72022-02-11 21:43:505278 first_key = dictionary.keys[0]
5279 first_value = dictionary.values[0]
5280 second_key = dictionary.keys[1]
5281 second_value = dictionary.values[1]
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205282
Sam Maiera6e76d72022-02-11 21:43:505283 if (not isinstance(first_key, ast.Str)
5284 or first_key.s != 'WATCHLIST_DEFINITIONS'
5285 or not isinstance(first_value, ast.Dict)):
5286 return ('The first entry of the dict in WATCHLISTS file must be '
5287 'WATCHLIST_DEFINITIONS dict')
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205288
Sam Maiera6e76d72022-02-11 21:43:505289 if (not isinstance(second_key, ast.Str) or second_key.s != 'WATCHLISTS'
5290 or not isinstance(second_value, ast.Dict)):
5291 return ('The second entry of the dict in WATCHLISTS file must be '
5292 'WATCHLISTS dict')
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205293
Sam Maiera6e76d72022-02-11 21:43:505294 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:135295
5296
Saagar Sanghavifceeaae2020-08-12 16:40:365297def CheckWATCHLISTS(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505298 for f in input_api.AffectedFiles(include_deletes=False):
5299 if f.LocalPath() == 'WATCHLISTS':
5300 contents = input_api.ReadFile(f, 'r')
Takeshi Yoshinoe387aa32017-08-02 13:16:135301
Sam Maiera6e76d72022-02-11 21:43:505302 try:
5303 # First, make sure that it can be evaluated.
5304 input_api.ast.literal_eval(contents)
5305 # Get an AST tree for it and scan the tree for detailed style checking.
5306 expression = input_api.ast.parse(contents,
5307 filename='WATCHLISTS',
5308 mode='eval')
5309 except ValueError as e:
5310 return [
5311 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5312 long_text=repr(e))
5313 ]
5314 except SyntaxError as e:
5315 return [
5316 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5317 long_text=repr(e))
5318 ]
5319 except TypeError as e:
5320 return [
5321 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5322 long_text=repr(e))
5323 ]
Takeshi Yoshinoe387aa32017-08-02 13:16:135324
Sam Maiera6e76d72022-02-11 21:43:505325 result = _CheckWATCHLISTSSyntax(expression, input_api)
5326 if result is not None:
5327 return [output_api.PresubmitError(result)]
5328 break
Takeshi Yoshinoe387aa32017-08-02 13:16:135329
Sam Maiera6e76d72022-02-11 21:43:505330 return []
Takeshi Yoshinoe387aa32017-08-02 13:16:135331
Sean Kaucb7c9b32022-10-25 21:25:525332def CheckGnRebasePath(input_api, output_api):
5333 """Checks that target_gen_dir is not used wtih "//" in rebase_path().
5334
5335 Developers should use root_build_dir instead of "//" when using target_gen_dir because
5336 Chromium is sometimes built outside of the source tree.
5337 """
5338
5339 def gn_files(f):
5340 return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn', ))
5341
5342 rebase_path_regex = input_api.re.compile(r'rebase_path\(("\$target_gen_dir"|target_gen_dir), ("/"|"//")\)')
5343 problems = []
5344 for f in input_api.AffectedSourceFiles(gn_files):
5345 for line_num, line in f.ChangedContents():
5346 if rebase_path_regex.search(line):
5347 problems.append(
5348 'Absolute path in rebase_path() in %s:%d' %
5349 (f.LocalPath(), line_num))
5350
5351 if problems:
5352 return [
5353 output_api.PresubmitPromptWarning(
5354 'Using an absolute path in rebase_path()',
5355 items=sorted(problems),
5356 long_text=(
5357 'rebase_path() should use root_build_dir instead of "/" ',
5358 'since builds can be initiated from outside of the source ',
5359 'root.'))
5360 ]
5361 return []
Takeshi Yoshinoe387aa32017-08-02 13:16:135362
Andrew Grieve1b290e4a22020-11-24 20:07:015363def CheckGnGlobForward(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505364 """Checks that forward_variables_from(invoker, "*") follows best practices.
Andrew Grieve1b290e4a22020-11-24 20:07:015365
Sam Maiera6e76d72022-02-11 21:43:505366 As documented at //build/docs/writing_gn_templates.md
5367 """
Andrew Grieve1b290e4a22020-11-24 20:07:015368
Sam Maiera6e76d72022-02-11 21:43:505369 def gn_files(f):
5370 return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gni', ))
Andrew Grieve1b290e4a22020-11-24 20:07:015371
Sam Maiera6e76d72022-02-11 21:43:505372 problems = []
5373 for f in input_api.AffectedSourceFiles(gn_files):
5374 for line_num, line in f.ChangedContents():
5375 if 'forward_variables_from(invoker, "*")' in line:
5376 problems.append(
5377 'Bare forward_variables_from(invoker, "*") in %s:%d' %
5378 (f.LocalPath(), line_num))
5379
5380 if problems:
5381 return [
5382 output_api.PresubmitPromptWarning(
5383 'forward_variables_from("*") without exclusions',
5384 items=sorted(problems),
5385 long_text=(
Gao Shenga79ebd42022-08-08 17:25:595386 'The variables "visibility" and "test_only" should be '
Sam Maiera6e76d72022-02-11 21:43:505387 'explicitly listed in forward_variables_from(). For more '
5388 'details, see:\n'
5389 'https://chromium.googlesource.com/chromium/src/+/HEAD/'
5390 'build/docs/writing_gn_templates.md'
5391 '#Using-forward_variables_from'))
5392 ]
5393 return []
Andrew Grieve1b290e4a22020-11-24 20:07:015394
Saagar Sanghavifceeaae2020-08-12 16:40:365395def CheckNewHeaderWithoutGnChangeOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505396 """Checks that newly added header files have corresponding GN changes.
5397 Note that this is only a heuristic. To be precise, run script:
5398 build/check_gn_headers.py.
5399 """
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195400
Sam Maiera6e76d72022-02-11 21:43:505401 def headers(f):
5402 return input_api.FilterSourceFile(
5403 f, files_to_check=(r'.+%s' % _HEADER_EXTENSIONS, ))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195404
Sam Maiera6e76d72022-02-11 21:43:505405 new_headers = []
5406 for f in input_api.AffectedSourceFiles(headers):
5407 if f.Action() != 'A':
5408 continue
5409 new_headers.append(f.LocalPath())
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195410
Sam Maiera6e76d72022-02-11 21:43:505411 def gn_files(f):
5412 return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn', ))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195413
Sam Maiera6e76d72022-02-11 21:43:505414 all_gn_changed_contents = ''
5415 for f in input_api.AffectedSourceFiles(gn_files):
5416 for _, line in f.ChangedContents():
5417 all_gn_changed_contents += line
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195418
Sam Maiera6e76d72022-02-11 21:43:505419 problems = []
5420 for header in new_headers:
5421 basename = input_api.os_path.basename(header)
5422 if basename not in all_gn_changed_contents:
5423 problems.append(header)
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195424
Sam Maiera6e76d72022-02-11 21:43:505425 if problems:
5426 return [
5427 output_api.PresubmitPromptWarning(
5428 'Missing GN changes for new header files',
5429 items=sorted(problems),
5430 long_text=
5431 'Please double check whether newly added header files need '
5432 'corresponding changes in gn or gni files.\nThis checking is only a '
5433 'heuristic. Run build/check_gn_headers.py to be precise.\n'
5434 'Read https://crbug.com/661774 for more info.')
5435 ]
5436 return []
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195437
5438
Saagar Sanghavifceeaae2020-08-12 16:40:365439def CheckCorrectProductNameInMessages(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505440 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
Michael Giuffridad3bc8672018-10-25 22:48:025441
Sam Maiera6e76d72022-02-11 21:43:505442 This assumes we won't intentionally reference one product from the other
5443 product.
5444 """
5445 all_problems = []
5446 test_cases = [{
5447 "filename_postfix": "google_chrome_strings.grd",
5448 "correct_name": "Chrome",
5449 "incorrect_name": "Chromium",
5450 }, {
Thiago Perrotta099034f2023-06-05 18:10:205451 "filename_postfix": "google_chrome_strings.grd",
5452 "correct_name": "Chrome",
5453 "incorrect_name": "Chrome for Testing",
5454 }, {
Sam Maiera6e76d72022-02-11 21:43:505455 "filename_postfix": "chromium_strings.grd",
5456 "correct_name": "Chromium",
5457 "incorrect_name": "Chrome",
5458 }]
Michael Giuffridad3bc8672018-10-25 22:48:025459
Sam Maiera6e76d72022-02-11 21:43:505460 for test_case in test_cases:
5461 problems = []
5462 filename_filter = lambda x: x.LocalPath().endswith(test_case[
5463 "filename_postfix"])
Michael Giuffridad3bc8672018-10-25 22:48:025464
Sam Maiera6e76d72022-02-11 21:43:505465 # Check each new line. Can yield false positives in multiline comments, but
5466 # easier than trying to parse the XML because messages can have nested
5467 # children, and associating message elements with affected lines is hard.
5468 for f in input_api.AffectedSourceFiles(filename_filter):
5469 for line_num, line in f.ChangedContents():
5470 if "<message" in line or "<!--" in line or "-->" in line:
5471 continue
5472 if test_case["incorrect_name"] in line:
Thiago Perrotta099034f2023-06-05 18:10:205473 # Chrome for Testing is a special edge case: https://goo.gle/chrome-for-testing#bookmark=id.n1rat320av91
5474 if (test_case["correct_name"] == "Chromium" and line.count("Chrome") == line.count("Chrome for Testing")):
5475 continue
Sam Maiera6e76d72022-02-11 21:43:505476 problems.append("Incorrect product name in %s:%d" %
5477 (f.LocalPath(), line_num))
Michael Giuffridad3bc8672018-10-25 22:48:025478
Sam Maiera6e76d72022-02-11 21:43:505479 if problems:
5480 message = (
5481 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
5482 % (test_case["correct_name"], test_case["correct_name"],
5483 test_case["incorrect_name"]))
5484 all_problems.append(
5485 output_api.PresubmitPromptWarning(message, items=problems))
Michael Giuffridad3bc8672018-10-25 22:48:025486
Sam Maiera6e76d72022-02-11 21:43:505487 return all_problems
Michael Giuffridad3bc8672018-10-25 22:48:025488
5489
Saagar Sanghavifceeaae2020-08-12 16:40:365490def CheckForTooLargeFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505491 """Avoid large files, especially binary files, in the repository since
5492 git doesn't scale well for those. They will be in everyone's repo
5493 clones forever, forever making Chromium slower to clone and work
5494 with."""
Daniel Bratell93eb6c62019-04-29 20:13:365495
Sam Maiera6e76d72022-02-11 21:43:505496 # Uploading files to cloud storage is not trivial so we don't want
5497 # to set the limit too low, but the upper limit for "normal" large
5498 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
5499 # anything over 20 MB is exceptional.
Bruce Dawsonbb414db2022-12-27 20:21:255500 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024
Daniel Bratell93eb6c62019-04-29 20:13:365501
Sam Maiera6e76d72022-02-11 21:43:505502 too_large_files = []
5503 for f in input_api.AffectedFiles():
5504 # Check both added and modified files (but not deleted files).
5505 if f.Action() in ('A', 'M'):
5506 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Joe DeBlasio10a832f2023-04-21 20:20:185507 if size > TOO_LARGE_FILE_SIZE_LIMIT:
Sam Maiera6e76d72022-02-11 21:43:505508 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
Daniel Bratell93eb6c62019-04-29 20:13:365509
Sam Maiera6e76d72022-02-11 21:43:505510 if too_large_files:
5511 message = (
5512 'Do not commit large files to git since git scales badly for those.\n'
5513 +
5514 'Instead put the large files in cloud storage and use DEPS to\n' +
5515 'fetch them.\n' + '\n'.join(too_large_files))
5516 return [
5517 output_api.PresubmitError('Too large files found in commit',
5518 long_text=message + '\n')
5519 ]
5520 else:
5521 return []
Daniel Bratell93eb6c62019-04-29 20:13:365522
Max Morozb47503b2019-08-08 21:03:275523
Saagar Sanghavifceeaae2020-08-12 16:40:365524def CheckFuzzTargetsOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505525 """Checks specific for fuzz target sources."""
5526 EXPORTED_SYMBOLS = [
5527 'LLVMFuzzerInitialize',
5528 'LLVMFuzzerCustomMutator',
5529 'LLVMFuzzerCustomCrossOver',
5530 'LLVMFuzzerMutate',
5531 ]
Max Morozb47503b2019-08-08 21:03:275532
Sam Maiera6e76d72022-02-11 21:43:505533 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
Max Morozb47503b2019-08-08 21:03:275534
Sam Maiera6e76d72022-02-11 21:43:505535 def FilterFile(affected_file):
5536 """Ignore libFuzzer source code."""
5537 files_to_check = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
Bruce Dawson40fece62022-09-16 19:58:315538 files_to_skip = r"^third_party/libFuzzer"
Max Morozb47503b2019-08-08 21:03:275539
Sam Maiera6e76d72022-02-11 21:43:505540 return input_api.FilterSourceFile(affected_file,
5541 files_to_check=[files_to_check],
5542 files_to_skip=[files_to_skip])
Max Morozb47503b2019-08-08 21:03:275543
Sam Maiera6e76d72022-02-11 21:43:505544 files_with_missing_header = []
5545 for f in input_api.AffectedSourceFiles(FilterFile):
5546 contents = input_api.ReadFile(f, 'r')
5547 if REQUIRED_HEADER in contents:
5548 continue
Max Morozb47503b2019-08-08 21:03:275549
Sam Maiera6e76d72022-02-11 21:43:505550 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
5551 files_with_missing_header.append(f.LocalPath())
Max Morozb47503b2019-08-08 21:03:275552
Sam Maiera6e76d72022-02-11 21:43:505553 if not files_with_missing_header:
5554 return []
Max Morozb47503b2019-08-08 21:03:275555
Sam Maiera6e76d72022-02-11 21:43:505556 long_text = (
5557 'If you define any of the libFuzzer optional functions (%s), it is '
5558 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
5559 'work incorrectly on Mac (crbug.com/687076).\nNote that '
5560 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
5561 'to access command line arguments passed to the fuzzer. Instead, prefer '
5562 'static initialization and shared resources as documented in '
5563 'https://chromium.googlesource.com/chromium/src/+/main/testing/'
5564 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n'
5565 % (', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER))
Max Morozb47503b2019-08-08 21:03:275566
Sam Maiera6e76d72022-02-11 21:43:505567 return [
5568 output_api.PresubmitPromptWarning(message="Missing '%s' in:" %
5569 REQUIRED_HEADER,
5570 items=files_with_missing_header,
5571 long_text=long_text)
5572 ]
Max Morozb47503b2019-08-08 21:03:275573
5574
Mohamed Heikald048240a2019-11-12 16:57:375575def _CheckNewImagesWarning(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505576 """
5577 Warns authors who add images into the repo to make sure their images are
5578 optimized before committing.
5579 """
5580 images_added = False
5581 image_paths = []
5582 errors = []
5583 filter_lambda = lambda x: input_api.FilterSourceFile(
5584 x,
5585 files_to_skip=(('(?i).*test', r'.*\/junit\/') + input_api.
5586 DEFAULT_FILES_TO_SKIP),
5587 files_to_check=[r'.*\/(drawable|mipmap)'])
5588 for f in input_api.AffectedFiles(include_deletes=False,
5589 file_filter=filter_lambda):
5590 local_path = f.LocalPath().lower()
5591 if any(
5592 local_path.endswith(extension)
5593 for extension in _IMAGE_EXTENSIONS):
5594 images_added = True
5595 image_paths.append(f)
5596 if images_added:
5597 errors.append(
5598 output_api.PresubmitPromptWarning(
5599 'It looks like you are trying to commit some images. If these are '
5600 'non-test-only images, please make sure to read and apply the tips in '
5601 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
5602 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
5603 'FYI only and will not block your CL on the CQ.', image_paths))
5604 return errors
Mohamed Heikald048240a2019-11-12 16:57:375605
5606
Saagar Sanghavifceeaae2020-08-12 16:40:365607def ChecksAndroidSpecificOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505608 """Groups upload checks that target android code."""
5609 results = []
5610 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
5611 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
5612 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
5613 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:505614 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
5615 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
5616 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
5617 results.extend(_CheckNewImagesWarning(input_api, output_api))
5618 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
5619 results.extend(_CheckAndroidInfoBarDeprecation(input_api, output_api))
5620 return results
5621
Becky Zhou7c69b50992018-12-10 19:37:575622
Saagar Sanghavifceeaae2020-08-12 16:40:365623def ChecksAndroidSpecificOnCommit(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505624 """Groups commit checks that target android code."""
5625 results = []
5626 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
5627 return results
dgnaa68d5e2015-06-10 10:08:225628
Chris Hall59f8d0c72020-05-01 07:31:195629# TODO(chrishall): could we additionally match on any path owned by
5630# ui/accessibility/OWNERS ?
5631_ACCESSIBILITY_PATHS = (
Bruce Dawson40fece62022-09-16 19:58:315632 r"^chrome/browser.*/accessibility/",
5633 r"^chrome/browser/extensions/api/automation.*/",
5634 r"^chrome/renderer/extensions/accessibility_.*",
5635 r"^chrome/tests/data/accessibility/",
5636 r"^content/browser/accessibility/",
5637 r"^content/renderer/accessibility/",
5638 r"^content/tests/data/accessibility/",
5639 r"^extensions/renderer/api/automation/",
Katie Dektar58ef07b2022-09-27 13:19:175640 r"^services/accessibility/",
Abigail Klein7a63c572024-02-28 20:45:095641 r"^services/screen_ai/",
Bruce Dawson40fece62022-09-16 19:58:315642 r"^ui/accessibility/",
5643 r"^ui/views/accessibility/",
Chris Hall59f8d0c72020-05-01 07:31:195644)
5645
Saagar Sanghavifceeaae2020-08-12 16:40:365646def CheckAccessibilityRelnotesField(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505647 """Checks that commits to accessibility code contain an AX-Relnotes field in
5648 their commit message."""
Chris Hall59f8d0c72020-05-01 07:31:195649
Sam Maiera6e76d72022-02-11 21:43:505650 def FileFilter(affected_file):
5651 paths = _ACCESSIBILITY_PATHS
5652 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Chris Hall59f8d0c72020-05-01 07:31:195653
Sam Maiera6e76d72022-02-11 21:43:505654 # Only consider changes affecting accessibility paths.
5655 if not any(input_api.AffectedFiles(file_filter=FileFilter)):
5656 return []
Akihiro Ota08108e542020-05-20 15:30:535657
Sam Maiera6e76d72022-02-11 21:43:505658 # AX-Relnotes can appear in either the description or the footer.
5659 # When searching the description, require 'AX-Relnotes:' to appear at the
5660 # beginning of a line.
5661 ax_regex = input_api.re.compile('ax-relnotes[:=]')
5662 description_has_relnotes = any(
5663 ax_regex.match(line)
5664 for line in input_api.change.DescriptionText().lower().splitlines())
Chris Hall59f8d0c72020-05-01 07:31:195665
Sam Maiera6e76d72022-02-11 21:43:505666 footer_relnotes = input_api.change.GitFootersFromDescription().get(
5667 'AX-Relnotes', [])
5668 if description_has_relnotes or footer_relnotes:
5669 return []
Chris Hall59f8d0c72020-05-01 07:31:195670
Sam Maiera6e76d72022-02-11 21:43:505671 # TODO(chrishall): link to Relnotes documentation in message.
5672 message = (
5673 "Missing 'AX-Relnotes:' field required for accessibility changes"
5674 "\n please add 'AX-Relnotes: [release notes].' to describe any "
5675 "user-facing changes"
5676 "\n otherwise add 'AX-Relnotes: n/a.' if this change has no "
5677 "user-facing effects"
5678 "\n if this is confusing or annoying then please contact members "
5679 "of ui/accessibility/OWNERS.")
5680
5681 return [output_api.PresubmitNotifyResult(message)]
dgnaa68d5e2015-06-10 10:08:225682
Mark Schillacie5a0be22022-01-19 00:38:395683
5684_ACCESSIBILITY_EVENTS_TEST_PATH = (
Bruce Dawson40fece62022-09-16 19:58:315685 r"^content/test/data/accessibility/event/.*\.html",
Mark Schillacie5a0be22022-01-19 00:38:395686)
5687
5688_ACCESSIBILITY_TREE_TEST_PATH = (
Aaron Leventhal267119f2023-08-18 22:45:345689 r"^content/test/data/accessibility/accname/"
5690 ".*-expected-(mac|win|uia-win|auralinux).txt",
5691 r"^content/test/data/accessibility/aria/"
5692 ".*-expected-(mac|win|uia-win|auralinux).txt",
5693 r"^content/test/data/accessibility/css/"
5694 ".*-expected-(mac|win|uia-win|auralinux).txt",
5695 r"^content/test/data/accessibility/event/"
5696 ".*-expected-(mac|win|uia-win|auralinux).txt",
5697 r"^content/test/data/accessibility/html/"
5698 ".*-expected-(mac|win|uia-win|auralinux).txt",
Mark Schillacie5a0be22022-01-19 00:38:395699)
5700
5701_ACCESSIBILITY_ANDROID_EVENTS_TEST_PATH = (
Bruce Dawson40fece62022-09-16 19:58:315702 r"^.*/WebContentsAccessibilityEventsTest\.java",
Mark Schillacie5a0be22022-01-19 00:38:395703)
5704
5705_ACCESSIBILITY_ANDROID_TREE_TEST_PATH = (
Bruce Dawson40fece62022-09-16 19:58:315706 r"^.*/WebContentsAccessibilityTreeTest\.java",
Mark Schillacie5a0be22022-01-19 00:38:395707)
5708
5709def CheckAccessibilityEventsTestsAreIncludedForAndroid(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505710 """Checks that commits that include a newly added, renamed/moved, or deleted
5711 test in the DumpAccessibilityEventsTest suite also includes a corresponding
5712 change to the Android test."""
Mark Schillacie5a0be22022-01-19 00:38:395713
Sam Maiera6e76d72022-02-11 21:43:505714 def FilePathFilter(affected_file):
5715 paths = _ACCESSIBILITY_EVENTS_TEST_PATH
5716 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395717
Sam Maiera6e76d72022-02-11 21:43:505718 def AndroidFilePathFilter(affected_file):
5719 paths = _ACCESSIBILITY_ANDROID_EVENTS_TEST_PATH
5720 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395721
Sam Maiera6e76d72022-02-11 21:43:505722 # Only consider changes in the events test data path with html type.
5723 if not any(
5724 input_api.AffectedFiles(include_deletes=True,
5725 file_filter=FilePathFilter)):
5726 return []
Mark Schillacie5a0be22022-01-19 00:38:395727
Sam Maiera6e76d72022-02-11 21:43:505728 # If the commit contains any change to the Android test file, ignore.
5729 if any(
5730 input_api.AffectedFiles(include_deletes=True,
5731 file_filter=AndroidFilePathFilter)):
5732 return []
Mark Schillacie5a0be22022-01-19 00:38:395733
Sam Maiera6e76d72022-02-11 21:43:505734 # Only consider changes that are adding/renaming or deleting a file
5735 message = []
5736 for f in input_api.AffectedFiles(include_deletes=True,
5737 file_filter=FilePathFilter):
Aaron Leventhal267119f2023-08-18 22:45:345738 if f.Action() == 'A':
Sam Maiera6e76d72022-02-11 21:43:505739 message = (
Aaron Leventhal267119f2023-08-18 22:45:345740 "It appears that you are adding platform expectations for a"
Aaron Leventhal0de81072023-08-21 21:26:525741 "\ndump_accessibility_events* test, but have not included"
Sam Maiera6e76d72022-02-11 21:43:505742 "\na corresponding change for Android."
Aaron Leventhal267119f2023-08-18 22:45:345743 "\nPlease include the test from:"
Sam Maiera6e76d72022-02-11 21:43:505744 "\n content/public/android/javatests/src/org/chromium/"
5745 "content/browser/accessibility/"
5746 "WebContentsAccessibilityEventsTest.java"
5747 "\nIf this message is confusing or annoying, please contact"
5748 "\nmembers of ui/accessibility/OWNERS.")
Mark Schillacie5a0be22022-01-19 00:38:395749
Sam Maiera6e76d72022-02-11 21:43:505750 # If no message was set, return empty.
5751 if not len(message):
5752 return []
5753
5754 return [output_api.PresubmitPromptWarning(message)]
5755
Mark Schillacie5a0be22022-01-19 00:38:395756
5757def CheckAccessibilityTreeTestsAreIncludedForAndroid(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505758 """Checks that commits that include a newly added, renamed/moved, or deleted
5759 test in the DumpAccessibilityTreeTest suite also includes a corresponding
5760 change to the Android test."""
Mark Schillacie5a0be22022-01-19 00:38:395761
Sam Maiera6e76d72022-02-11 21:43:505762 def FilePathFilter(affected_file):
5763 paths = _ACCESSIBILITY_TREE_TEST_PATH
5764 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395765
Sam Maiera6e76d72022-02-11 21:43:505766 def AndroidFilePathFilter(affected_file):
5767 paths = _ACCESSIBILITY_ANDROID_TREE_TEST_PATH
5768 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395769
Sam Maiera6e76d72022-02-11 21:43:505770 # Only consider changes in the various tree test data paths with html type.
5771 if not any(
5772 input_api.AffectedFiles(include_deletes=True,
5773 file_filter=FilePathFilter)):
5774 return []
Mark Schillacie5a0be22022-01-19 00:38:395775
Sam Maiera6e76d72022-02-11 21:43:505776 # If the commit contains any change to the Android test file, ignore.
5777 if any(
5778 input_api.AffectedFiles(include_deletes=True,
5779 file_filter=AndroidFilePathFilter)):
5780 return []
Mark Schillacie5a0be22022-01-19 00:38:395781
Sam Maiera6e76d72022-02-11 21:43:505782 # Only consider changes that are adding/renaming or deleting a file
5783 message = []
5784 for f in input_api.AffectedFiles(include_deletes=True,
5785 file_filter=FilePathFilter):
Aaron Leventhal0de81072023-08-21 21:26:525786 if f.Action() == 'A':
Sam Maiera6e76d72022-02-11 21:43:505787 message = (
Aaron Leventhal0de81072023-08-21 21:26:525788 "It appears that you are adding platform expectations for a"
5789 "\ndump_accessibility_tree* test, but have not included"
Sam Maiera6e76d72022-02-11 21:43:505790 "\na corresponding change for Android."
5791 "\nPlease include (or remove) the test from:"
5792 "\n content/public/android/javatests/src/org/chromium/"
5793 "content/browser/accessibility/"
5794 "WebContentsAccessibilityTreeTest.java"
5795 "\nIf this message is confusing or annoying, please contact"
5796 "\nmembers of ui/accessibility/OWNERS.")
Mark Schillacie5a0be22022-01-19 00:38:395797
Sam Maiera6e76d72022-02-11 21:43:505798 # If no message was set, return empty.
5799 if not len(message):
5800 return []
5801
5802 return [output_api.PresubmitPromptWarning(message)]
Mark Schillacie5a0be22022-01-19 00:38:395803
5804
Bruce Dawson33806592022-11-16 01:44:515805def CheckEsLintConfigChanges(input_api, output_api):
5806 """Suggest using "git cl presubmit --files" when .eslintrc.js files are
5807 modified. This is important because enabling an error in .eslintrc.js can
5808 trigger errors in any .js or .ts files in its directory, leading to hidden
5809 presubmit errors."""
5810 results = []
5811 eslint_filter = lambda f: input_api.FilterSourceFile(
5812 f, files_to_check=[r'.*\.eslintrc\.js$'])
5813 for f in input_api.AffectedFiles(include_deletes=False,
5814 file_filter=eslint_filter):
5815 local_dir = input_api.os_path.dirname(f.LocalPath())
5816 # Use / characters so that the commands printed work on any OS.
5817 local_dir = local_dir.replace(input_api.os_path.sep, '/')
5818 if local_dir:
5819 local_dir += '/'
5820 results.append(
5821 output_api.PresubmitNotifyResult(
5822 '%(file)s modified. Consider running \'git cl presubmit --files '
5823 '"%(dir)s*.js;%(dir)s*.ts"\' in order to check and fix the affected '
5824 'files before landing this change.' %
5825 { 'file' : f.LocalPath(), 'dir' : local_dir}))
5826 return results
5827
5828
seanmccullough4a9356252021-04-08 19:54:095829# string pattern, sequence of strings to show when pattern matches,
5830# error flag. True if match is a presubmit error, otherwise it's a warning.
5831_NON_INCLUSIVE_TERMS = (
5832 (
5833 # Note that \b pattern in python re is pretty particular. In this
5834 # regexp, 'class WhiteList ...' will match, but 'class FooWhiteList
5835 # ...' will not. This may require some tweaking to catch these cases
5836 # without triggering a lot of false positives. Leaving it naive and
5837 # less matchy for now.
Josip Sokcevic9d2806a02023-12-13 03:04:025838 r'/(?i)\b((black|white)list|master|slave)\b', # nocheck
seanmccullough4a9356252021-04-08 19:54:095839 (
5840 'Please don\'t use blacklist, whitelist, ' # nocheck
5841 'or slave in your', # nocheck
5842 'code and make every effort to use other terms. Using "// nocheck"',
5843 '"# nocheck" or "<!-- nocheck -->"',
5844 'at the end of the offending line will bypass this PRESUBMIT error',
5845 'but avoid using this whenever possible. Reach out to',
5846 '[email protected] if you have questions'),
5847 True),)
5848
Saagar Sanghavifceeaae2020-08-12 16:40:365849def ChecksCommon(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505850 """Checks common to both upload and commit."""
5851 results = []
Eric Boren6fd2b932018-01-25 15:05:085852 results.extend(
Sam Maiera6e76d72022-02-11 21:43:505853 input_api.canned_checks.PanProjectChecks(
5854 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:085855
Sam Maiera6e76d72022-02-11 21:43:505856 author = input_api.change.author_email
5857 if author and author not in _KNOWN_ROBOTS:
5858 results.extend(
5859 input_api.canned_checks.CheckAuthorizedAuthor(
5860 input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:245861
Sam Maiera6e76d72022-02-11 21:43:505862 results.extend(
5863 input_api.canned_checks.CheckChangeHasNoTabs(
5864 input_api,
5865 output_api,
5866 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
5867 results.extend(
5868 input_api.RunTests(
5869 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Edward Lesmesce51df52020-08-04 22:10:175870
Bruce Dawsonc8054482022-03-28 15:33:375871 dirmd = 'dirmd.bat' if input_api.is_windows else 'dirmd'
Sam Maiera6e76d72022-02-11 21:43:505872 dirmd_bin = input_api.os_path.join(input_api.PresubmitLocalPath(),
Bruce Dawsonc8054482022-03-28 15:33:375873 'third_party', 'depot_tools', dirmd)
Sam Maiera6e76d72022-02-11 21:43:505874 results.extend(
5875 input_api.RunTests(
5876 input_api.canned_checks.CheckDirMetadataFormat(
5877 input_api, output_api, dirmd_bin)))
5878 results.extend(
5879 input_api.canned_checks.CheckOwnersDirMetadataExclusive(
5880 input_api, output_api))
5881 results.extend(
5882 input_api.canned_checks.CheckNoNewMetadataInOwners(
5883 input_api, output_api))
5884 results.extend(
5885 input_api.canned_checks.CheckInclusiveLanguage(
5886 input_api,
5887 output_api,
5888 excluded_directories_relative_path=[
5889 'infra', 'inclusive_language_presubmit_exempt_dirs.txt'
5890 ],
5891 non_inclusive_terms=_NON_INCLUSIVE_TERMS))
Dirk Prankee3c9c62d2021-05-18 18:35:595892
Aleksey Khoroshilov2978c942022-06-13 16:14:125893 presubmit_py_filter = lambda f: input_api.FilterSourceFile(
Bruce Dawson696963f2022-09-13 01:15:475894 f, files_to_check=[r'.*PRESUBMIT\.py$'])
Aleksey Khoroshilov2978c942022-06-13 16:14:125895 for f in input_api.AffectedFiles(include_deletes=False,
5896 file_filter=presubmit_py_filter):
5897 full_path = input_api.os_path.dirname(f.AbsoluteLocalPath())
5898 test_file = input_api.os_path.join(full_path, 'PRESUBMIT_test.py')
5899 # The PRESUBMIT.py file (and the directory containing it) might have
5900 # been affected by being moved or removed, so only try to run the tests
5901 # if they still exist.
5902 if not input_api.os_path.exists(test_file):
5903 continue
Sam Maiera6e76d72022-02-11 21:43:505904
Aleksey Khoroshilov2978c942022-06-13 16:14:125905 results.extend(
5906 input_api.canned_checks.RunUnitTestsInDirectory(
5907 input_api,
5908 output_api,
5909 full_path,
Takuto Ikuta40def482023-06-02 02:23:495910 files_to_check=[r'^PRESUBMIT_test\.py$']))
Sam Maiera6e76d72022-02-11 21:43:505911 return results
[email protected]1f7b4172010-01-28 01:17:345912
[email protected]b337cb5b2011-01-23 21:24:055913
Saagar Sanghavifceeaae2020-08-12 16:40:365914def CheckPatchFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505915 problems = [
5916 f.LocalPath() for f in input_api.AffectedFiles()
5917 if f.LocalPath().endswith(('.orig', '.rej'))
5918 ]
5919 # Cargo.toml.orig files are part of third-party crates downloaded from
5920 # crates.io and should be included.
5921 problems = [f for f in problems if not f.endswith('Cargo.toml.orig')]
5922 if problems:
5923 return [
5924 output_api.PresubmitError("Don't commit .rej and .orig files.",
5925 problems)
5926 ]
5927 else:
5928 return []
[email protected]b8079ae4a2012-12-05 19:56:495929
5930
Saagar Sanghavifceeaae2020-08-12 16:40:365931def CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505932 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
5933 macro_re = input_api.re.compile(
5934 r'^\s*#(el)?if.*\bdefined\(((COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
5935 include_re = input_api.re.compile(r'^#include\s+"build/build_config.h"',
5936 input_api.re.MULTILINE)
5937 extension_re = input_api.re.compile(r'\.[a-z]+$')
5938 errors = []
Bruce Dawsonf7679202022-08-09 20:24:005939 config_h_file = input_api.os_path.join('build', 'build_config.h')
Sam Maiera6e76d72022-02-11 21:43:505940 for f in input_api.AffectedFiles(include_deletes=False):
Bruce Dawsonf7679202022-08-09 20:24:005941 # The build-config macros are allowed to be used in build_config.h
5942 # without including itself.
5943 if f.LocalPath() == config_h_file:
5944 continue
Sam Maiera6e76d72022-02-11 21:43:505945 if not f.LocalPath().endswith(
5946 ('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
5947 continue
Arthur Sonzognia3dec412024-04-29 12:05:375948
5949 # See https://crbug.com/1508847. Temporary exclusion for PartitionAlloc,
5950 # the time for its dependency on //build to be removed.
5951 # PartitionAlloc has its own version of this script. See
5952 # base/allocator/partition_alloc/PRESUBMIT.py
5953 if "base/allocator/partition_allocator/" in f.LocalPath():
5954 continue
5955
Sam Maiera6e76d72022-02-11 21:43:505956 found_line_number = None
5957 found_macro = None
5958 all_lines = input_api.ReadFile(f, 'r').splitlines()
5959 for line_num, line in enumerate(all_lines):
5960 match = macro_re.search(line)
5961 if match:
5962 found_line_number = line_num
5963 found_macro = match.group(2)
5964 break
5965 if not found_line_number:
5966 continue
Kent Tamura5a8755d2017-06-29 23:37:075967
Sam Maiera6e76d72022-02-11 21:43:505968 found_include_line = -1
5969 for line_num, line in enumerate(all_lines):
5970 if include_re.search(line):
5971 found_include_line = line_num
5972 break
5973 if found_include_line >= 0 and found_include_line < found_line_number:
5974 continue
Kent Tamura5a8755d2017-06-29 23:37:075975
Sam Maiera6e76d72022-02-11 21:43:505976 if not f.LocalPath().endswith('.h'):
5977 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
5978 try:
5979 content = input_api.ReadFile(primary_header_path, 'r')
5980 if include_re.search(content):
5981 continue
5982 except IOError:
5983 pass
5984 errors.append('%s:%d %s macro is used without first including build/'
5985 'build_config.h.' %
5986 (f.LocalPath(), found_line_number, found_macro))
5987 if errors:
5988 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
5989 return []
Kent Tamura5a8755d2017-06-29 23:37:075990
5991
Lei Zhang1c12a22f2021-05-12 11:28:455992def CheckForSuperfluousStlIncludesInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505993 stl_include_re = input_api.re.compile(r'^#include\s+<('
5994 r'algorithm|'
5995 r'array|'
5996 r'limits|'
5997 r'list|'
5998 r'map|'
5999 r'memory|'
6000 r'queue|'
6001 r'set|'
6002 r'string|'
6003 r'unordered_map|'
6004 r'unordered_set|'
6005 r'utility|'
6006 r'vector)>')
6007 std_namespace_re = input_api.re.compile(r'std::')
6008 errors = []
6009 for f in input_api.AffectedFiles():
6010 if not _IsCPlusPlusHeaderFile(input_api, f.LocalPath()):
6011 continue
Lei Zhang1c12a22f2021-05-12 11:28:456012
Sam Maiera6e76d72022-02-11 21:43:506013 uses_std_namespace = False
6014 has_stl_include = False
6015 for line in f.NewContents():
6016 if has_stl_include and uses_std_namespace:
6017 break
Lei Zhang1c12a22f2021-05-12 11:28:456018
Sam Maiera6e76d72022-02-11 21:43:506019 if not has_stl_include and stl_include_re.search(line):
6020 has_stl_include = True
6021 continue
Lei Zhang1c12a22f2021-05-12 11:28:456022
Bruce Dawson4a5579a2022-04-08 17:11:366023 if not uses_std_namespace and (std_namespace_re.search(line)
6024 or 'no-std-usage-because-pch-file' in line):
Sam Maiera6e76d72022-02-11 21:43:506025 uses_std_namespace = True
6026 continue
Lei Zhang1c12a22f2021-05-12 11:28:456027
Sam Maiera6e76d72022-02-11 21:43:506028 if has_stl_include and not uses_std_namespace:
6029 errors.append(
6030 '%s: Includes STL header(s) but does not reference std::' %
6031 f.LocalPath())
6032 if errors:
6033 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
6034 return []
Lei Zhang1c12a22f2021-05-12 11:28:456035
6036
Xiaohan Wang42d96c22022-01-20 17:23:116037def _CheckForDeprecatedOSMacrosInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:506038 """Check for sensible looking, totally invalid OS macros."""
6039 preprocessor_statement = input_api.re.compile(r'^\s*#')
6040 os_macro = input_api.re.compile(r'defined\(OS_([^)]+)\)')
6041 results = []
6042 for lnum, line in f.ChangedContents():
6043 if preprocessor_statement.search(line):
6044 for match in os_macro.finditer(line):
6045 results.append(
6046 ' %s:%d: %s' %
6047 (f.LocalPath(), lnum, 'defined(OS_' + match.group(1) +
6048 ') -> BUILDFLAG(IS_' + match.group(1) + ')'))
6049 return results
[email protected]b00342e7f2013-03-26 16:21:546050
6051
Xiaohan Wang42d96c22022-01-20 17:23:116052def CheckForDeprecatedOSMacros(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506053 """Check all affected files for invalid OS macros."""
6054 bad_macros = []
Bruce Dawsonf7679202022-08-09 20:24:006055 # The OS_ macros are allowed to be used in build/build_config.h.
6056 config_h_file = input_api.os_path.join('build', 'build_config.h')
Sam Maiera6e76d72022-02-11 21:43:506057 for f in input_api.AffectedSourceFiles(None):
Bruce Dawsonf7679202022-08-09 20:24:006058 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')) \
6059 and f.LocalPath() != config_h_file:
Sam Maiera6e76d72022-02-11 21:43:506060 bad_macros.extend(_CheckForDeprecatedOSMacrosInFile(input_api, f))
[email protected]b00342e7f2013-03-26 16:21:546061
Sam Maiera6e76d72022-02-11 21:43:506062 if not bad_macros:
6063 return []
[email protected]b00342e7f2013-03-26 16:21:546064
Sam Maiera6e76d72022-02-11 21:43:506065 return [
6066 output_api.PresubmitError(
6067 'OS macros have been deprecated. Please use BUILDFLAGs instead (still '
6068 'defined in build_config.h):', bad_macros)
6069 ]
[email protected]b00342e7f2013-03-26 16:21:546070
lliabraa35bab3932014-10-01 12:16:446071
6072def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:506073 """Check all affected files for invalid "if defined" macros."""
6074 ALWAYS_DEFINED_MACROS = (
6075 "TARGET_CPU_PPC",
6076 "TARGET_CPU_PPC64",
6077 "TARGET_CPU_68K",
6078 "TARGET_CPU_X86",
6079 "TARGET_CPU_ARM",
6080 "TARGET_CPU_MIPS",
6081 "TARGET_CPU_SPARC",
6082 "TARGET_CPU_ALPHA",
6083 "TARGET_IPHONE_SIMULATOR",
6084 "TARGET_OS_EMBEDDED",
6085 "TARGET_OS_IPHONE",
6086 "TARGET_OS_MAC",
6087 "TARGET_OS_UNIX",
6088 "TARGET_OS_WIN32",
6089 )
6090 ifdef_macro = input_api.re.compile(
6091 r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
6092 results = []
6093 for lnum, line in f.ChangedContents():
6094 for match in ifdef_macro.finditer(line):
6095 if match.group(1) in ALWAYS_DEFINED_MACROS:
6096 always_defined = ' %s is always defined. ' % match.group(1)
6097 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
6098 results.append(
6099 ' %s:%d %s\n\t%s' %
6100 (f.LocalPath(), lnum, always_defined, did_you_mean))
6101 return results
lliabraa35bab3932014-10-01 12:16:446102
6103
Saagar Sanghavifceeaae2020-08-12 16:40:366104def CheckForInvalidIfDefinedMacros(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506105 """Check all affected files for invalid "if defined" macros."""
Arthur Sonzogni4fd14fd2024-06-02 18:42:526106 SKIPPED_PATHS = [
6107 'base/allocator/partition_allocator/src/partition_alloc/build_config.h',
6108 'build/build_config.h',
6109 'third_party/abseil-cpp/',
6110 'third_party/sqlite/',
6111 ]
6112 def affected_files_filter(f):
6113 # Normalize the local path to Linux-style path separators so that the
6114 # path comparisons work on Windows as well.
6115 path = f.LocalPath().replace('\\', '/')
6116
6117 for skipped_path in SKIPPED_PATHS:
6118 if path.startswith(skipped_path):
6119 return False
6120
6121 return path.endswith(('.h', '.c', '.cc', '.m', '.mm'))
6122
Sam Maiera6e76d72022-02-11 21:43:506123 bad_macros = []
Arthur Sonzogni4fd14fd2024-06-02 18:42:526124 for f in input_api.AffectedSourceFiles(affected_files_filter):
6125 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
lliabraa35bab3932014-10-01 12:16:446126
Sam Maiera6e76d72022-02-11 21:43:506127 if not bad_macros:
6128 return []
lliabraa35bab3932014-10-01 12:16:446129
Sam Maiera6e76d72022-02-11 21:43:506130 return [
6131 output_api.PresubmitError(
6132 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
6133 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
6134 bad_macros)
6135 ]
lliabraa35bab3932014-10-01 12:16:446136
Saagar Sanghavifceeaae2020-08-12 16:40:366137def CheckForIPCRules(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506138 """Check for same IPC rules described in
6139 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
6140 """
6141 base_pattern = r'IPC_ENUM_TRAITS\('
6142 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
6143 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
mlamouria82272622014-09-16 18:45:046144
Sam Maiera6e76d72022-02-11 21:43:506145 problems = []
6146 for f in input_api.AffectedSourceFiles(None):
6147 local_path = f.LocalPath()
6148 if not local_path.endswith('.h'):
6149 continue
6150 for line_number, line in f.ChangedContents():
6151 if inclusion_pattern.search(
6152 line) and not comment_pattern.search(line):
6153 problems.append('%s:%d\n %s' %
6154 (local_path, line_number, line.strip()))
mlamouria82272622014-09-16 18:45:046155
Sam Maiera6e76d72022-02-11 21:43:506156 if problems:
6157 return [
6158 output_api.PresubmitPromptWarning(_IPC_ENUM_TRAITS_DEPRECATED,
6159 problems)
6160 ]
6161 else:
6162 return []
mlamouria82272622014-09-16 18:45:046163
[email protected]b00342e7f2013-03-26 16:21:546164
Saagar Sanghavifceeaae2020-08-12 16:40:366165def CheckForLongPathnames(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506166 """Check to make sure no files being submitted have long paths.
6167 This causes issues on Windows.
6168 """
6169 problems = []
6170 for f in input_api.AffectedTestableFiles():
6171 local_path = f.LocalPath()
6172 # Windows has a path limit of 260 characters. Limit path length to 200 so
6173 # that we have some extra for the prefix on dev machines and the bots.
6174 if len(local_path) > 200:
6175 problems.append(local_path)
Stephen Martinis97a394142018-06-07 23:06:056176
Sam Maiera6e76d72022-02-11 21:43:506177 if problems:
6178 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
6179 else:
6180 return []
Stephen Martinis97a394142018-06-07 23:06:056181
6182
Saagar Sanghavifceeaae2020-08-12 16:40:366183def CheckForIncludeGuards(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506184 """Check that header files have proper guards against multiple inclusion.
6185 If a file should not have such guards (and it probably should) then it
Bruce Dawson4a5579a2022-04-08 17:11:366186 should include the string "no-include-guard-because-multiply-included" or
6187 "no-include-guard-because-pch-file".
Sam Maiera6e76d72022-02-11 21:43:506188 """
Daniel Bratell8ba52722018-03-02 16:06:146189
Sam Maiera6e76d72022-02-11 21:43:506190 def is_chromium_header_file(f):
6191 # We only check header files under the control of the Chromium
mikt84d6c712024-03-27 13:29:036192 # project. This excludes:
6193 # - third_party/*, except blink.
6194 # - base/allocator/partition_allocator/: PartitionAlloc is a standalone
6195 # library used outside of Chrome. Includes are referenced from its
6196 # own base directory. It has its own `CheckForIncludeGuards`
6197 # PRESUBMIT.py check.
6198 # - *_message_generator.h: They use include guards in a special,
6199 # non-typical way.
Sam Maiera6e76d72022-02-11 21:43:506200 file_with_path = input_api.os_path.normpath(f.LocalPath())
6201 return (file_with_path.endswith('.h')
6202 and not file_with_path.endswith('_message_generator.h')
Bruce Dawson4c4c2922022-05-02 18:07:336203 and not file_with_path.endswith('com_imported_mstscax.h')
mikt84d6c712024-03-27 13:29:036204 and not file_with_path.startswith('base/allocator/partition_allocator')
Sam Maiera6e76d72022-02-11 21:43:506205 and (not file_with_path.startswith('third_party')
6206 or file_with_path.startswith(
6207 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:146208
Sam Maiera6e76d72022-02-11 21:43:506209 def replace_special_with_underscore(string):
6210 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:146211
Sam Maiera6e76d72022-02-11 21:43:506212 errors = []
Daniel Bratell8ba52722018-03-02 16:06:146213
Sam Maiera6e76d72022-02-11 21:43:506214 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
6215 guard_name = None
6216 guard_line_number = None
6217 seen_guard_end = False
Lei Zhangd84f9512024-05-28 19:43:306218 bypass_checks_at_end_of_file = False
Daniel Bratell8ba52722018-03-02 16:06:146219
Sam Maiera6e76d72022-02-11 21:43:506220 file_with_path = input_api.os_path.normpath(f.LocalPath())
6221 base_file_name = input_api.os_path.splitext(
6222 input_api.os_path.basename(file_with_path))[0]
6223 upper_base_file_name = base_file_name.upper()
Daniel Bratell8ba52722018-03-02 16:06:146224
Sam Maiera6e76d72022-02-11 21:43:506225 expected_guard = replace_special_with_underscore(
6226 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:146227
Sam Maiera6e76d72022-02-11 21:43:506228 # For "path/elem/file_name.h" we should really only accept
6229 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
6230 # are too many (1000+) files with slight deviations from the
6231 # coding style. The most important part is that the include guard
6232 # is there, and that it's unique, not the name so this check is
6233 # forgiving for existing files.
6234 #
6235 # As code becomes more uniform, this could be made stricter.
Daniel Bratell8ba52722018-03-02 16:06:146236
Sam Maiera6e76d72022-02-11 21:43:506237 guard_name_pattern_list = [
6238 # Anything with the right suffix (maybe with an extra _).
6239 r'\w+_H__?',
Daniel Bratell8ba52722018-03-02 16:06:146240
Sam Maiera6e76d72022-02-11 21:43:506241 # To cover include guards with old Blink style.
6242 r'\w+_h',
Daniel Bratell8ba52722018-03-02 16:06:146243
Sam Maiera6e76d72022-02-11 21:43:506244 # Anything including the uppercase name of the file.
6245 r'\w*' + input_api.re.escape(
6246 replace_special_with_underscore(upper_base_file_name)) +
6247 r'\w*',
6248 ]
6249 guard_name_pattern = '|'.join(guard_name_pattern_list)
6250 guard_pattern = input_api.re.compile(r'#ifndef\s+(' +
6251 guard_name_pattern + ')')
Daniel Bratell8ba52722018-03-02 16:06:146252
Sam Maiera6e76d72022-02-11 21:43:506253 for line_number, line in enumerate(f.NewContents()):
Bruce Dawson4a5579a2022-04-08 17:11:366254 if ('no-include-guard-because-multiply-included' in line
6255 or 'no-include-guard-because-pch-file' in line):
Lei Zhangd84f9512024-05-28 19:43:306256 bypass_checks_at_end_of_file = True
Sam Maiera6e76d72022-02-11 21:43:506257 break
Daniel Bratell8ba52722018-03-02 16:06:146258
Sam Maiera6e76d72022-02-11 21:43:506259 if guard_name is None:
6260 match = guard_pattern.match(line)
6261 if match:
6262 guard_name = match.group(1)
6263 guard_line_number = line_number
Daniel Bratell8ba52722018-03-02 16:06:146264
Sam Maiera6e76d72022-02-11 21:43:506265 # We allow existing files to use include guards whose names
6266 # don't match the chromium style guide, but new files should
6267 # get it right.
Bruce Dawson6cc154e2022-04-12 20:39:496268 if guard_name != expected_guard:
Bruce Dawson95eb7562022-09-14 15:27:166269 if f.Action() == 'A': # If file was just 'A'dded
Sam Maiera6e76d72022-02-11 21:43:506270 errors.append(
6271 output_api.PresubmitPromptWarning(
6272 'Header using the wrong include guard name %s'
6273 % guard_name, [
6274 '%s:%d' %
6275 (f.LocalPath(), line_number + 1)
6276 ], 'Expected: %r\nFound: %r' %
6277 (expected_guard, guard_name)))
6278 else:
6279 # The line after #ifndef should have a #define of the same name.
6280 if line_number == guard_line_number + 1:
6281 expected_line = '#define %s' % guard_name
6282 if line != expected_line:
6283 errors.append(
6284 output_api.PresubmitPromptWarning(
6285 'Missing "%s" for include guard' %
6286 expected_line,
6287 ['%s:%d' % (f.LocalPath(), line_number + 1)],
6288 'Expected: %r\nGot: %r' %
6289 (expected_line, line)))
Daniel Bratell8ba52722018-03-02 16:06:146290
Sam Maiera6e76d72022-02-11 21:43:506291 if not seen_guard_end and line == '#endif // %s' % guard_name:
6292 seen_guard_end = True
6293 elif seen_guard_end:
6294 if line.strip() != '':
6295 errors.append(
6296 output_api.PresubmitPromptWarning(
6297 'Include guard %s not covering the whole file'
6298 % (guard_name), [f.LocalPath()]))
6299 break # Nothing else to check and enough to warn once.
Daniel Bratell8ba52722018-03-02 16:06:146300
Lei Zhangd84f9512024-05-28 19:43:306301 if bypass_checks_at_end_of_file:
6302 continue
6303
Sam Maiera6e76d72022-02-11 21:43:506304 if guard_name is None:
6305 errors.append(
6306 output_api.PresubmitPromptWarning(
Bruce Dawson32114b62022-04-11 16:45:496307 'Missing include guard in %s\n'
Sam Maiera6e76d72022-02-11 21:43:506308 'Recommended name: %s\n'
6309 'This check can be disabled by having the string\n'
Bruce Dawson4a5579a2022-04-08 17:11:366310 '"no-include-guard-because-multiply-included" or\n'
6311 '"no-include-guard-because-pch-file" in the header.'
Sam Maiera6e76d72022-02-11 21:43:506312 % (f.LocalPath(), expected_guard)))
Lei Zhangd84f9512024-05-28 19:43:306313 elif not seen_guard_end:
6314 errors.append(
6315 output_api.PresubmitPromptWarning(
6316 'Incorrect or missing include guard #endif in %s\n'
6317 'Recommended #endif comment: // %s'
6318 % (f.LocalPath(), expected_guard)))
Sam Maiera6e76d72022-02-11 21:43:506319
6320 return errors
Daniel Bratell8ba52722018-03-02 16:06:146321
6322
Saagar Sanghavifceeaae2020-08-12 16:40:366323def CheckForWindowsLineEndings(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506324 """Check source code and known ascii text files for Windows style line
6325 endings.
6326 """
Bruce Dawson5efbdc652022-04-11 19:29:516327 known_text_files = r'.*\.(txt|html|htm|py|gyp|gypi|gn|isolate|icon)$'
mostynbb639aca52015-01-07 20:31:236328
Sam Maiera6e76d72022-02-11 21:43:506329 file_inclusion_pattern = (known_text_files,
6330 r'.+%s' % _IMPLEMENTATION_EXTENSIONS,
6331 r'.+%s' % _HEADER_EXTENSIONS)
mostynbb639aca52015-01-07 20:31:236332
Sam Maiera6e76d72022-02-11 21:43:506333 problems = []
6334 source_file_filter = lambda f: input_api.FilterSourceFile(
6335 f, files_to_check=file_inclusion_pattern, files_to_skip=None)
6336 for f in input_api.AffectedSourceFiles(source_file_filter):
Bruce Dawson5efbdc652022-04-11 19:29:516337 # Ignore test files that contain crlf intentionally.
6338 if f.LocalPath().endswith('crlf.txt'):
Daniel Chenga37c03db2022-05-12 17:20:346339 continue
Sam Maiera6e76d72022-02-11 21:43:506340 include_file = False
6341 for line in input_api.ReadFile(f, 'r').splitlines(True):
6342 if line.endswith('\r\n'):
6343 include_file = True
6344 if include_file:
6345 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:236346
Sam Maiera6e76d72022-02-11 21:43:506347 if problems:
6348 return [
6349 output_api.PresubmitPromptWarning(
6350 'Are you sure that you want '
6351 'these files to contain Windows style line endings?\n' +
6352 '\n'.join(problems))
6353 ]
mostynbb639aca52015-01-07 20:31:236354
Sam Maiera6e76d72022-02-11 21:43:506355 return []
6356
mostynbb639aca52015-01-07 20:31:236357
Evan Stade6cfc964c12021-05-18 20:21:166358def CheckIconFilesForLicenseHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506359 """Check that .icon files (which are fragments of C++) have license headers.
6360 """
Evan Stade6cfc964c12021-05-18 20:21:166361
Sam Maiera6e76d72022-02-11 21:43:506362 icon_files = (r'.*\.icon$', )
Evan Stade6cfc964c12021-05-18 20:21:166363
Sam Maiera6e76d72022-02-11 21:43:506364 icons = lambda x: input_api.FilterSourceFile(x, files_to_check=icon_files)
6365 return input_api.canned_checks.CheckLicense(input_api,
6366 output_api,
6367 source_file_filter=icons)
6368
Evan Stade6cfc964c12021-05-18 20:21:166369
Jose Magana2b456f22021-03-09 23:26:406370def CheckForUseOfChromeAppsDeprecations(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506371 """Check source code for use of Chrome App technologies being
6372 deprecated.
6373 """
Jose Magana2b456f22021-03-09 23:26:406374
Sam Maiera6e76d72022-02-11 21:43:506375 def _CheckForDeprecatedTech(input_api,
6376 output_api,
6377 detection_list,
6378 files_to_check=None,
6379 files_to_skip=None):
Jose Magana2b456f22021-03-09 23:26:406380
Sam Maiera6e76d72022-02-11 21:43:506381 if (files_to_check or files_to_skip):
6382 source_file_filter = lambda f: input_api.FilterSourceFile(
6383 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
6384 else:
6385 source_file_filter = None
6386
6387 problems = []
6388
6389 for f in input_api.AffectedSourceFiles(source_file_filter):
6390 if f.Action() == 'D':
6391 continue
6392 for _, line in f.ChangedContents():
6393 if any(detect in line for detect in detection_list):
6394 problems.append(f.LocalPath())
6395
6396 return problems
6397
6398 # to avoid this presubmit script triggering warnings
6399 files_to_skip = ['PRESUBMIT.py', 'PRESUBMIT_test.py']
Jose Magana2b456f22021-03-09 23:26:406400
6401 problems = []
6402
Sam Maiera6e76d72022-02-11 21:43:506403 # NMF: any files with extensions .nmf or NMF
6404 _NMF_FILES = r'\.(nmf|NMF)$'
6405 problems += _CheckForDeprecatedTech(
6406 input_api,
6407 output_api,
6408 detection_list=[''], # any change to the file will trigger warning
6409 files_to_check=[r'.+%s' % _NMF_FILES])
Jose Magana2b456f22021-03-09 23:26:406410
Sam Maiera6e76d72022-02-11 21:43:506411 # MANIFEST: any manifest.json that in its diff includes "app":
6412 _MANIFEST_FILES = r'(manifest\.json)$'
6413 problems += _CheckForDeprecatedTech(
6414 input_api,
6415 output_api,
6416 detection_list=['"app":'],
6417 files_to_check=[r'.*%s' % _MANIFEST_FILES])
Jose Magana2b456f22021-03-09 23:26:406418
Sam Maiera6e76d72022-02-11 21:43:506419 # NaCl / PNaCl: any file that in its diff contains the strings in the list
6420 problems += _CheckForDeprecatedTech(
6421 input_api,
6422 output_api,
6423 detection_list=['config=nacl', 'enable-nacl', 'cpu=pnacl', 'nacl_io'],
Bruce Dawson40fece62022-09-16 19:58:316424 files_to_skip=files_to_skip + [r"^native_client_sdk/"])
Jose Magana2b456f22021-03-09 23:26:406425
Gao Shenga79ebd42022-08-08 17:25:596426 # PPAPI: any C/C++ file that in its diff includes a ppapi library
Sam Maiera6e76d72022-02-11 21:43:506427 problems += _CheckForDeprecatedTech(
6428 input_api,
6429 output_api,
6430 detection_list=['#include "ppapi', '#include <ppapi'],
6431 files_to_check=(r'.+%s' % _HEADER_EXTENSIONS,
6432 r'.+%s' % _IMPLEMENTATION_EXTENSIONS),
Bruce Dawson40fece62022-09-16 19:58:316433 files_to_skip=[r"^ppapi/"])
Jose Magana2b456f22021-03-09 23:26:406434
Sam Maiera6e76d72022-02-11 21:43:506435 if problems:
6436 return [
6437 output_api.PresubmitPromptWarning(
6438 'You are adding/modifying code'
6439 'related to technologies which will soon be deprecated (Chrome Apps, NaCl,'
6440 ' PNaCl, PPAPI). See this blog post for more details:\n'
6441 'https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html\n'
6442 'and this documentation for options to replace these technologies:\n'
6443 'https://developer.chrome.com/docs/apps/migration/\n' +
6444 '\n'.join(problems))
6445 ]
Jose Magana2b456f22021-03-09 23:26:406446
Sam Maiera6e76d72022-02-11 21:43:506447 return []
Jose Magana2b456f22021-03-09 23:26:406448
mostynbb639aca52015-01-07 20:31:236449
Saagar Sanghavifceeaae2020-08-12 16:40:366450def CheckSyslogUseWarningOnUpload(input_api, output_api, src_file_filter=None):
Sam Maiera6e76d72022-02-11 21:43:506451 """Checks that all source files use SYSLOG properly."""
6452 syslog_files = []
6453 for f in input_api.AffectedSourceFiles(src_file_filter):
6454 for line_number, line in f.ChangedContents():
6455 if 'SYSLOG' in line:
6456 syslog_files.append(f.LocalPath() + ':' + str(line_number))
pastarmovj032ba5bc2017-01-12 10:41:566457
Sam Maiera6e76d72022-02-11 21:43:506458 if syslog_files:
6459 return [
6460 output_api.PresubmitPromptWarning(
6461 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
6462 ' calls.\nFiles to check:\n',
6463 items=syslog_files)
6464 ]
6465 return []
pastarmovj89f7ee12016-09-20 14:58:136466
6467
[email protected]1f7b4172010-01-28 01:17:346468def CheckChangeOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506469 if input_api.version < [2, 0, 0]:
6470 return [
6471 output_api.PresubmitError(
6472 "Your depot_tools is out of date. "
6473 "This PRESUBMIT.py requires at least presubmit_support version 2.0.0, "
6474 "but your version is %d.%d.%d" % tuple(input_api.version))
6475 ]
6476 results = []
6477 results.extend(
6478 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
6479 return results
[email protected]ca8d1982009-02-19 16:33:126480
6481
6482def CheckChangeOnCommit(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506483 if input_api.version < [2, 0, 0]:
6484 return [
6485 output_api.PresubmitError(
6486 "Your depot_tools is out of date. "
6487 "This PRESUBMIT.py requires at least presubmit_support version 2.0.0, "
6488 "but your version is %d.%d.%d" % tuple(input_api.version))
6489 ]
Saagar Sanghavifceeaae2020-08-12 16:40:366490
Sam Maiera6e76d72022-02-11 21:43:506491 results = []
6492 # Make sure the tree is 'open'.
6493 results.extend(
6494 input_api.canned_checks.CheckTreeIsOpen(
6495 input_api,
6496 output_api,
6497 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:276498
Sam Maiera6e76d72022-02-11 21:43:506499 results.extend(
6500 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
6501 results.extend(
6502 input_api.canned_checks.CheckChangeHasBugField(input_api, output_api))
6503 results.extend(
6504 input_api.canned_checks.CheckChangeHasNoUnwantedTags(
6505 input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:506506 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146507
6508
Saagar Sanghavifceeaae2020-08-12 16:40:366509def CheckStrings(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506510 """Check string ICU syntax validity and if translation screenshots exist."""
6511 # Skip translation screenshots check if a SkipTranslationScreenshotsCheck
6512 # footer is set to true.
6513 git_footers = input_api.change.GitFootersFromDescription()
6514 skip_screenshot_check_footer = [
6515 footer.lower() for footer in git_footers.get(
6516 u'Skip-Translation-Screenshots-Check', [])
6517 ]
6518 run_screenshot_check = u'true' not in skip_screenshot_check_footer
Edward Lesmesf7c5c6d2020-05-14 23:30:026519
Sam Maiera6e76d72022-02-11 21:43:506520 import os
6521 import re
6522 import sys
6523 from io import StringIO
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146524
Sam Maiera6e76d72022-02-11 21:43:506525 new_or_added_paths = set(f.LocalPath() for f in input_api.AffectedFiles()
6526 if (f.Action() == 'A' or f.Action() == 'M'))
6527 removed_paths = set(f.LocalPath()
6528 for f in input_api.AffectedFiles(include_deletes=True)
6529 if f.Action() == 'D')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146530
Sam Maiera6e76d72022-02-11 21:43:506531 affected_grds = [
6532 f for f in input_api.AffectedFiles()
6533 if f.LocalPath().endswith(('.grd', '.grdp'))
6534 ]
6535 affected_grds = [
6536 f for f in affected_grds if not 'testdata' in f.LocalPath()
6537 ]
6538 if not affected_grds:
6539 return []
meacer8c0d3832019-12-26 21:46:166540
Sam Maiera6e76d72022-02-11 21:43:506541 affected_png_paths = [
6542 f.AbsoluteLocalPath() for f in input_api.AffectedFiles()
6543 if (f.LocalPath().endswith('.png'))
6544 ]
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146545
Sam Maiera6e76d72022-02-11 21:43:506546 # Check for screenshots. Developers can upload screenshots using
6547 # tools/translation/upload_screenshots.py which finds and uploads
6548 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
6549 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
6550 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
6551 #
6552 # The logic here is as follows:
6553 #
6554 # - If the CL has a .png file under the screenshots directory for a grd
6555 # file, warn the developer. Actual images should never be checked into the
6556 # Chrome repo.
6557 #
6558 # - If the CL contains modified or new messages in grd files and doesn't
6559 # contain the corresponding .sha1 files, warn the developer to add images
6560 # and upload them via tools/translation/upload_screenshots.py.
6561 #
6562 # - If the CL contains modified or new messages in grd files and the
6563 # corresponding .sha1 files, everything looks good.
6564 #
6565 # - If the CL contains removed messages in grd files but the corresponding
6566 # .sha1 files aren't removed, warn the developer to remove them.
6567 unnecessary_screenshots = []
Jens Mueller054652c2023-05-10 15:12:306568 invalid_sha1 = []
Sam Maiera6e76d72022-02-11 21:43:506569 missing_sha1 = []
Bruce Dawson55776c42022-12-09 17:23:476570 missing_sha1_modified = []
Sam Maiera6e76d72022-02-11 21:43:506571 unnecessary_sha1_files = []
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146572
Sam Maiera6e76d72022-02-11 21:43:506573 # This checks verifies that the ICU syntax of messages this CL touched is
6574 # valid, and reports any found syntax errors.
6575 # Without this presubmit check, ICU syntax errors in Chromium strings can land
6576 # without developers being aware of them. Later on, such ICU syntax errors
6577 # break message extraction for translation, hence would block Chromium
6578 # translations until they are fixed.
6579 icu_syntax_errors = []
Jens Mueller054652c2023-05-10 15:12:306580 sha1_pattern = input_api.re.compile(r'^[a-fA-F0-9]{40}$',
6581 input_api.re.MULTILINE)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146582
Sam Maiera6e76d72022-02-11 21:43:506583 def _CheckScreenshotAdded(screenshots_dir, message_id):
6584 sha1_path = input_api.os_path.join(screenshots_dir,
6585 message_id + '.png.sha1')
6586 if sha1_path not in new_or_added_paths:
6587 missing_sha1.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:306588 elif not _CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:256589 invalid_sha1.append(sha1_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146590
Bruce Dawson55776c42022-12-09 17:23:476591 def _CheckScreenshotModified(screenshots_dir, message_id):
6592 sha1_path = input_api.os_path.join(screenshots_dir,
6593 message_id + '.png.sha1')
6594 if sha1_path not in new_or_added_paths:
6595 missing_sha1_modified.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:306596 elif not _CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:256597 invalid_sha1.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:306598
6599 def _CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:256600 return sha1_pattern.search(
6601 next("\n".join(f.NewContents()) for f in input_api.AffectedFiles()
6602 if f.LocalPath() == sha1_path))
Bruce Dawson55776c42022-12-09 17:23:476603
Sam Maiera6e76d72022-02-11 21:43:506604 def _CheckScreenshotRemoved(screenshots_dir, message_id):
6605 sha1_path = input_api.os_path.join(screenshots_dir,
6606 message_id + '.png.sha1')
6607 if input_api.os_path.exists(
6608 sha1_path) and sha1_path not in removed_paths:
6609 unnecessary_sha1_files.append(sha1_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146610
Sam Maiera6e76d72022-02-11 21:43:506611 def _ValidateIcuSyntax(text, level, signatures):
6612 """Validates ICU syntax of a text string.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146613
Sam Maiera6e76d72022-02-11 21:43:506614 Check if text looks similar to ICU and checks for ICU syntax correctness
6615 in this case. Reports various issues with ICU syntax and values of
6616 variants. Supports checking of nested messages. Accumulate information of
6617 each ICU messages found in the text for further checking.
Rainhard Findlingfc31844c52020-05-15 09:58:266618
Sam Maiera6e76d72022-02-11 21:43:506619 Args:
6620 text: a string to check.
6621 level: a number of current nesting level.
6622 signatures: an accumulator, a list of tuple of (level, variable,
6623 kind, variants).
Rainhard Findlingfc31844c52020-05-15 09:58:266624
Sam Maiera6e76d72022-02-11 21:43:506625 Returns:
6626 None if a string is not ICU or no issue detected.
6627 A tuple of (message, start index, end index) if an issue detected.
6628 """
6629 valid_types = {
6630 'plural': (frozenset(
Rainhard Findling3cde3ef02024-02-05 18:40:326631 ['=0', '=1', '=2', '=3', 'zero', 'one', 'two', 'few', 'many',
Sam Maiera6e76d72022-02-11 21:43:506632 'other']), frozenset(['=1', 'other'])),
6633 'selectordinal': (frozenset(
Rainhard Findling3cde3ef02024-02-05 18:40:326634 ['=0', '=1', '=2', '=3', 'zero', 'one', 'two', 'few', 'many',
Sam Maiera6e76d72022-02-11 21:43:506635 'other']), frozenset(['one', 'other'])),
6636 'select': (frozenset(), frozenset(['other'])),
6637 }
Rainhard Findlingfc31844c52020-05-15 09:58:266638
Sam Maiera6e76d72022-02-11 21:43:506639 # Check if the message looks like an attempt to use ICU
6640 # plural. If yes - check if its syntax strictly matches ICU format.
6641 like = re.match(r'^[^{]*\{[^{]*\b(plural|selectordinal|select)\b',
6642 text)
6643 if not like:
6644 signatures.append((level, None, None, None))
6645 return
Rainhard Findlingfc31844c52020-05-15 09:58:266646
Sam Maiera6e76d72022-02-11 21:43:506647 # Check for valid prefix and suffix
6648 m = re.match(
6649 r'^([^{]*\{)([a-zA-Z0-9_]+),\s*'
6650 r'(plural|selectordinal|select),\s*'
6651 r'(?:offset:\d+)?\s*(.*)', text, re.DOTALL)
6652 if not m:
6653 return (('This message looks like an ICU plural, '
6654 'but does not follow ICU syntax.'), like.start(),
6655 like.end())
6656 starting, variable, kind, variant_pairs = m.groups()
6657 variants, depth, last_pos = _ParseIcuVariants(variant_pairs,
6658 m.start(4))
6659 if depth:
6660 return ('Invalid ICU format. Unbalanced opening bracket', last_pos,
6661 len(text))
6662 first = text[0]
6663 ending = text[last_pos:]
6664 if not starting:
6665 return ('Invalid ICU format. No initial opening bracket',
6666 last_pos - 1, last_pos)
6667 if not ending or '}' not in ending:
6668 return ('Invalid ICU format. No final closing bracket',
6669 last_pos - 1, last_pos)
6670 elif first != '{':
6671 return ((
6672 'Invalid ICU format. Extra characters at the start of a complex '
6673 'message (go/icu-message-migration): "%s"') % starting, 0,
6674 len(starting))
6675 elif ending != '}':
6676 return ((
6677 'Invalid ICU format. Extra characters at the end of a complex '
6678 'message (go/icu-message-migration): "%s"') % ending,
6679 last_pos - 1, len(text) - 1)
6680 if kind not in valid_types:
6681 return (('Unknown ICU message type %s. '
6682 'Valid types are: plural, select, selectordinal') % kind,
6683 0, 0)
6684 known, required = valid_types[kind]
6685 defined_variants = set()
6686 for variant, variant_range, value, value_range in variants:
6687 start, end = variant_range
6688 if variant in defined_variants:
6689 return ('Variant "%s" is defined more than once' % variant,
6690 start, end)
6691 elif known and variant not in known:
6692 return ('Variant "%s" is not valid for %s message' %
6693 (variant, kind), start, end)
6694 defined_variants.add(variant)
6695 # Check for nested structure
6696 res = _ValidateIcuSyntax(value[1:-1], level + 1, signatures)
6697 if res:
6698 return (res[0], res[1] + value_range[0] + 1,
6699 res[2] + value_range[0] + 1)
6700 missing = required - defined_variants
6701 if missing:
6702 return ('Required variants missing: %s' % ', '.join(missing), 0,
6703 len(text))
6704 signatures.append((level, variable, kind, defined_variants))
Rainhard Findlingfc31844c52020-05-15 09:58:266705
Sam Maiera6e76d72022-02-11 21:43:506706 def _ParseIcuVariants(text, offset=0):
6707 """Parse variants part of ICU complex message.
Rainhard Findlingfc31844c52020-05-15 09:58:266708
Sam Maiera6e76d72022-02-11 21:43:506709 Builds a tuple of variant names and values, as well as
6710 their offsets in the input string.
Rainhard Findlingfc31844c52020-05-15 09:58:266711
Sam Maiera6e76d72022-02-11 21:43:506712 Args:
6713 text: a string to parse
6714 offset: additional offset to add to positions in the text to get correct
6715 position in the complete ICU string.
Rainhard Findlingfc31844c52020-05-15 09:58:266716
Sam Maiera6e76d72022-02-11 21:43:506717 Returns:
6718 List of tuples, each tuple consist of four fields: variant name,
6719 variant name span (tuple of two integers), variant value, value
6720 span (tuple of two integers).
6721 """
6722 depth, start, end = 0, -1, -1
6723 variants = []
6724 key = None
6725 for idx, char in enumerate(text):
6726 if char == '{':
6727 if not depth:
6728 start = idx
6729 chunk = text[end + 1:start]
6730 key = chunk.strip()
6731 pos = offset + end + 1 + chunk.find(key)
6732 span = (pos, pos + len(key))
6733 depth += 1
6734 elif char == '}':
6735 if not depth:
6736 return variants, depth, offset + idx
6737 depth -= 1
6738 if not depth:
6739 end = idx
6740 variants.append((key, span, text[start:end + 1],
6741 (offset + start, offset + end + 1)))
6742 return variants, depth, offset + end + 1
Rainhard Findlingfc31844c52020-05-15 09:58:266743
Sam Maiera6e76d72022-02-11 21:43:506744 try:
6745 old_sys_path = sys.path
6746 sys.path = sys.path + [
6747 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
6748 'translation')
6749 ]
6750 from helper import grd_helper
6751 finally:
6752 sys.path = old_sys_path
Rainhard Findlingfc31844c52020-05-15 09:58:266753
Sam Maiera6e76d72022-02-11 21:43:506754 for f in affected_grds:
6755 file_path = f.LocalPath()
6756 old_id_to_msg_map = {}
6757 new_id_to_msg_map = {}
6758 # Note that this code doesn't check if the file has been deleted. This is
6759 # OK because it only uses the old and new file contents and doesn't load
6760 # the file via its path.
6761 # It's also possible that a file's content refers to a renamed or deleted
6762 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
6763 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
6764 # .grdp files.
6765 if file_path.endswith('.grdp'):
6766 if f.OldContents():
6767 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
6768 '\n'.join(f.OldContents()))
6769 if f.NewContents():
6770 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
6771 '\n'.join(f.NewContents()))
6772 else:
6773 file_dir = input_api.os_path.dirname(file_path) or '.'
6774 if f.OldContents():
6775 old_id_to_msg_map = grd_helper.GetGrdMessages(
6776 StringIO('\n'.join(f.OldContents())), file_dir)
6777 if f.NewContents():
6778 new_id_to_msg_map = grd_helper.GetGrdMessages(
6779 StringIO('\n'.join(f.NewContents())), file_dir)
Rainhard Findlingfc31844c52020-05-15 09:58:266780
Sam Maiera6e76d72022-02-11 21:43:506781 grd_name, ext = input_api.os_path.splitext(
6782 input_api.os_path.basename(file_path))
6783 screenshots_dir = input_api.os_path.join(
6784 input_api.os_path.dirname(file_path),
6785 grd_name + ext.replace('.', '_'))
Rainhard Findlingfc31844c52020-05-15 09:58:266786
Sam Maiera6e76d72022-02-11 21:43:506787 # Compute added, removed and modified message IDs.
6788 old_ids = set(old_id_to_msg_map)
6789 new_ids = set(new_id_to_msg_map)
6790 added_ids = new_ids - old_ids
6791 removed_ids = old_ids - new_ids
6792 modified_ids = set([])
6793 for key in old_ids.intersection(new_ids):
6794 if (old_id_to_msg_map[key].ContentsAsXml('', True) !=
6795 new_id_to_msg_map[key].ContentsAsXml('', True)):
6796 # The message content itself changed. Require an updated screenshot.
6797 modified_ids.add(key)
6798 elif old_id_to_msg_map[key].attrs['meaning'] != \
6799 new_id_to_msg_map[key].attrs['meaning']:
Jens Mueller054652c2023-05-10 15:12:306800 # The message meaning changed. We later check for a screenshot.
6801 modified_ids.add(key)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146802
Sam Maiera6e76d72022-02-11 21:43:506803 if run_screenshot_check:
6804 # Check the screenshot directory for .png files. Warn if there is any.
6805 for png_path in affected_png_paths:
6806 if png_path.startswith(screenshots_dir):
6807 unnecessary_screenshots.append(png_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146808
Sam Maiera6e76d72022-02-11 21:43:506809 for added_id in added_ids:
6810 _CheckScreenshotAdded(screenshots_dir, added_id)
Rainhard Findlingd8d04372020-08-13 13:30:096811
Sam Maiera6e76d72022-02-11 21:43:506812 for modified_id in modified_ids:
Bruce Dawson55776c42022-12-09 17:23:476813 _CheckScreenshotModified(screenshots_dir, modified_id)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146814
Sam Maiera6e76d72022-02-11 21:43:506815 for removed_id in removed_ids:
6816 _CheckScreenshotRemoved(screenshots_dir, removed_id)
6817
6818 # Check new and changed strings for ICU syntax errors.
6819 for key in added_ids.union(modified_ids):
6820 msg = new_id_to_msg_map[key].ContentsAsXml('', True)
6821 err = _ValidateIcuSyntax(msg, 0, [])
6822 if err is not None:
6823 icu_syntax_errors.append(str(key) + ': ' + str(err[0]))
6824
6825 results = []
Rainhard Findlingfc31844c52020-05-15 09:58:266826 if run_screenshot_check:
Sam Maiera6e76d72022-02-11 21:43:506827 if unnecessary_screenshots:
6828 results.append(
6829 output_api.PresubmitError(
6830 'Do not include actual screenshots in the changelist. Run '
6831 'tools/translate/upload_screenshots.py to upload them instead:',
6832 sorted(unnecessary_screenshots)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146833
Sam Maiera6e76d72022-02-11 21:43:506834 if missing_sha1:
6835 results.append(
6836 output_api.PresubmitError(
Bruce Dawson55776c42022-12-09 17:23:476837 'You are adding UI strings.\n'
Sam Maiera6e76d72022-02-11 21:43:506838 'To ensure the best translations, take screenshots of the relevant UI '
6839 '(https://g.co/chrome/translation) and add these files to your '
6840 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146841
Jens Mueller054652c2023-05-10 15:12:306842 if invalid_sha1:
6843 results.append(
6844 output_api.PresubmitError(
6845 'The following files do not seem to contain valid sha1 hashes. '
6846 'Make sure they contain hashes created by '
6847 'tools/translate/upload_screenshots.py:', sorted(invalid_sha1)))
6848
Bruce Dawson55776c42022-12-09 17:23:476849 if missing_sha1_modified:
6850 results.append(
6851 output_api.PresubmitError(
6852 'You are modifying UI strings or their meanings.\n'
6853 'To ensure the best translations, take screenshots of the relevant UI '
6854 '(https://g.co/chrome/translation) and add these files to your '
6855 'changelist:', sorted(missing_sha1_modified)))
6856
Sam Maiera6e76d72022-02-11 21:43:506857 if unnecessary_sha1_files:
6858 results.append(
6859 output_api.PresubmitError(
6860 'You removed strings associated with these files. Remove:',
6861 sorted(unnecessary_sha1_files)))
6862 else:
6863 results.append(
6864 output_api.PresubmitPromptOrNotify('Skipping translation '
6865 'screenshots check.'))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146866
Sam Maiera6e76d72022-02-11 21:43:506867 if icu_syntax_errors:
6868 results.append(
6869 output_api.PresubmitPromptWarning(
6870 'ICU syntax errors were found in the following strings (problems or '
6871 'feedback? Contact [email protected]):',
6872 items=icu_syntax_errors))
Rainhard Findlingfc31844c52020-05-15 09:58:266873
Sam Maiera6e76d72022-02-11 21:43:506874 return results
Mustafa Emre Acer51f2f742020-03-09 19:41:126875
6876
Saagar Sanghavifceeaae2020-08-12 16:40:366877def CheckTranslationExpectations(input_api, output_api,
Mustafa Emre Acer51f2f742020-03-09 19:41:126878 repo_root=None,
6879 translation_expectations_path=None,
6880 grd_files=None):
Sam Maiera6e76d72022-02-11 21:43:506881 import sys
6882 affected_grds = [
6883 f for f in input_api.AffectedFiles()
6884 if (f.LocalPath().endswith('.grd') or f.LocalPath().endswith('.grdp'))
6885 ]
6886 if not affected_grds:
6887 return []
6888
6889 try:
6890 old_sys_path = sys.path
6891 sys.path = sys.path + [
6892 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
6893 'translation')
6894 ]
6895 from helper import git_helper
6896 from helper import translation_helper
6897 finally:
6898 sys.path = old_sys_path
6899
6900 # Check that translation expectations can be parsed and we can get a list of
6901 # translatable grd files. |repo_root| and |translation_expectations_path| are
6902 # only passed by tests.
6903 if not repo_root:
6904 repo_root = input_api.PresubmitLocalPath()
6905 if not translation_expectations_path:
6906 translation_expectations_path = input_api.os_path.join(
6907 repo_root, 'tools', 'gritsettings', 'translation_expectations.pyl')
6908 if not grd_files:
6909 grd_files = git_helper.list_grds_in_repository(repo_root)
6910
6911 # Ignore bogus grd files used only for testing
Gao Shenga79ebd42022-08-08 17:25:596912 # ui/webui/resources/tools/generate_grd.py.
Sam Maiera6e76d72022-02-11 21:43:506913 ignore_path = input_api.os_path.join('ui', 'webui', 'resources', 'tools',
6914 'tests')
6915 grd_files = [p for p in grd_files if ignore_path not in p]
6916
6917 try:
6918 translation_helper.get_translatable_grds(
6919 repo_root, grd_files, translation_expectations_path)
6920 except Exception as e:
6921 return [
6922 output_api.PresubmitNotifyResult(
6923 'Failed to get a list of translatable grd files. This happens when:\n'
6924 ' - One of the modified grd or grdp files cannot be parsed or\n'
6925 ' - %s is not updated.\n'
6926 'Stack:\n%s' % (translation_expectations_path, str(e)))
6927 ]
Mustafa Emre Acer51f2f742020-03-09 19:41:126928 return []
6929
Ken Rockotc31f4832020-05-29 18:58:516930
Saagar Sanghavifceeaae2020-08-12 16:40:366931def CheckStableMojomChanges(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506932 """Changes to [Stable] mojom types must preserve backward-compatibility."""
6933 changed_mojoms = input_api.AffectedFiles(
6934 include_deletes=True,
6935 file_filter=lambda f: f.LocalPath().endswith(('.mojom')))
Erik Staabc734cd7a2021-11-23 03:11:526936
Bruce Dawson344ab262022-06-04 11:35:106937 if not changed_mojoms or input_api.no_diffs:
Sam Maiera6e76d72022-02-11 21:43:506938 return []
6939
6940 delta = []
6941 for mojom in changed_mojoms:
Sam Maiera6e76d72022-02-11 21:43:506942 delta.append({
6943 'filename': mojom.LocalPath(),
6944 'old': '\n'.join(mojom.OldContents()) or None,
6945 'new': '\n'.join(mojom.NewContents()) or None,
6946 })
6947
6948 process = input_api.subprocess.Popen([
Takuto Ikutadca10222022-04-13 02:51:216949 input_api.python3_executable,
Sam Maiera6e76d72022-02-11 21:43:506950 input_api.os_path.join(
6951 input_api.PresubmitLocalPath(), 'mojo', 'public', 'tools', 'mojom',
6952 'check_stable_mojom_compatibility.py'), '--src-root',
6953 input_api.PresubmitLocalPath()
6954 ],
6955 stdin=input_api.subprocess.PIPE,
6956 stdout=input_api.subprocess.PIPE,
6957 stderr=input_api.subprocess.PIPE,
6958 universal_newlines=True)
6959 (x, error) = process.communicate(input=input_api.json.dumps(delta))
6960 if process.returncode:
6961 return [
6962 output_api.PresubmitError(
6963 'One or more [Stable] mojom definitions appears to have been changed '
Alex Goughc99921652024-02-15 22:59:126964 'in a way that is not backward-compatible. See '
6965 'https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/public/tools/bindings/README.md#versioning'
6966 ' for details.',
Sam Maiera6e76d72022-02-11 21:43:506967 long_text=error)
6968 ]
Erik Staabc734cd7a2021-11-23 03:11:526969 return []
6970
Dominic Battre645d42342020-12-04 16:14:106971def CheckDeprecationOfPreferences(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506972 """Removing a preference should come with a deprecation."""
Dominic Battre645d42342020-12-04 16:14:106973
Sam Maiera6e76d72022-02-11 21:43:506974 def FilterFile(affected_file):
6975 """Accept only .cc files and the like."""
6976 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
6977 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
6978 input_api.DEFAULT_FILES_TO_SKIP)
6979 return input_api.FilterSourceFile(
6980 affected_file,
6981 files_to_check=file_inclusion_pattern,
6982 files_to_skip=files_to_skip)
Dominic Battre645d42342020-12-04 16:14:106983
Sam Maiera6e76d72022-02-11 21:43:506984 def ModifiedLines(affected_file):
6985 """Returns a list of tuples (line number, line text) of added and removed
6986 lines.
Dominic Battre645d42342020-12-04 16:14:106987
Sam Maiera6e76d72022-02-11 21:43:506988 Deleted lines share the same line number as the previous line.
Dominic Battre645d42342020-12-04 16:14:106989
Sam Maiera6e76d72022-02-11 21:43:506990 This relies on the scm diff output describing each changed code section
6991 with a line of the form
Dominic Battre645d42342020-12-04 16:14:106992
Sam Maiera6e76d72022-02-11 21:43:506993 ^@@ <old line num>,<old size> <new line num>,<new size> @@$
6994 """
6995 line_num = 0
6996 modified_lines = []
6997 for line in affected_file.GenerateScmDiff().splitlines():
6998 # Extract <new line num> of the patch fragment (see format above).
6999 m = input_api.re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@',
7000 line)
7001 if m:
7002 line_num = int(m.groups(1)[0])
7003 continue
7004 if ((line.startswith('+') and not line.startswith('++'))
7005 or (line.startswith('-') and not line.startswith('--'))):
7006 modified_lines.append((line_num, line))
Dominic Battre645d42342020-12-04 16:14:107007
Sam Maiera6e76d72022-02-11 21:43:507008 if not line.startswith('-'):
7009 line_num += 1
7010 return modified_lines
Dominic Battre645d42342020-12-04 16:14:107011
Sam Maiera6e76d72022-02-11 21:43:507012 def FindLineWith(lines, needle):
7013 """Returns the line number (i.e. index + 1) in `lines` containing `needle`.
Dominic Battre645d42342020-12-04 16:14:107014
Sam Maiera6e76d72022-02-11 21:43:507015 If 0 or >1 lines contain `needle`, -1 is returned.
7016 """
7017 matching_line_numbers = [
7018 # + 1 for 1-based counting of line numbers.
7019 i + 1 for i, line in enumerate(lines) if needle in line
7020 ]
7021 return matching_line_numbers[0] if len(
7022 matching_line_numbers) == 1 else -1
Dominic Battre645d42342020-12-04 16:14:107023
Sam Maiera6e76d72022-02-11 21:43:507024 def ModifiedPrefMigration(affected_file):
7025 """Returns whether the MigrateObsolete.*Pref functions were modified."""
7026 # Determine first and last lines of MigrateObsolete.*Pref functions.
7027 new_contents = affected_file.NewContents()
7028 range_1 = (FindLineWith(new_contents,
7029 'BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'),
7030 FindLineWith(new_contents,
7031 'END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'))
7032 range_2 = (FindLineWith(new_contents,
7033 'BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS'),
7034 FindLineWith(new_contents,
7035 'END_MIGRATE_OBSOLETE_PROFILE_PREFS'))
7036 if (-1 in range_1 + range_2):
7037 raise Exception(
7038 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.'
7039 )
Dominic Battre645d42342020-12-04 16:14:107040
Sam Maiera6e76d72022-02-11 21:43:507041 # Check whether any of the modified lines are part of the
7042 # MigrateObsolete.*Pref functions.
7043 for line_nr, line in ModifiedLines(affected_file):
7044 if (range_1[0] <= line_nr <= range_1[1]
7045 or range_2[0] <= line_nr <= range_2[1]):
7046 return True
7047 return False
Dominic Battre645d42342020-12-04 16:14:107048
Sam Maiera6e76d72022-02-11 21:43:507049 register_pref_pattern = input_api.re.compile(r'Register.+Pref')
7050 browser_prefs_file_pattern = input_api.re.compile(
7051 r'chrome/browser/prefs/browser_prefs.cc')
Dominic Battre645d42342020-12-04 16:14:107052
Sam Maiera6e76d72022-02-11 21:43:507053 changes = input_api.AffectedFiles(include_deletes=True,
7054 file_filter=FilterFile)
7055 potential_problems = []
7056 for f in changes:
7057 for line in f.GenerateScmDiff().splitlines():
7058 # Check deleted lines for pref registrations.
7059 if (line.startswith('-') and not line.startswith('--')
7060 and register_pref_pattern.search(line)):
7061 potential_problems.append('%s: %s' % (f.LocalPath(), line))
Dominic Battre645d42342020-12-04 16:14:107062
Sam Maiera6e76d72022-02-11 21:43:507063 if browser_prefs_file_pattern.search(f.LocalPath()):
7064 # If the developer modified the MigrateObsolete.*Prefs() functions, we
7065 # assume that they knew that they have to deprecate preferences and don't
7066 # warn.
7067 try:
7068 if ModifiedPrefMigration(f):
7069 return []
7070 except Exception as e:
7071 return [output_api.PresubmitError(str(e))]
Dominic Battre645d42342020-12-04 16:14:107072
Sam Maiera6e76d72022-02-11 21:43:507073 if potential_problems:
7074 return [
7075 output_api.PresubmitPromptWarning(
7076 'Discovered possible removal of preference registrations.\n\n'
7077 'Please make sure to properly deprecate preferences by clearing their\n'
7078 'value for a couple of milestones before finally removing the code.\n'
7079 'Otherwise data may stay in the preferences files forever. See\n'
7080 'Migrate*Prefs() in chrome/browser/prefs/browser_prefs.cc and\n'
7081 'chrome/browser/prefs/README.md for examples.\n'
7082 'This may be a false positive warning (e.g. if you move preference\n'
7083 'registrations to a different place).\n', potential_problems)
7084 ]
7085 return []
7086
Matt Stark6ef08872021-07-29 01:21:467087
7088def CheckConsistentGrdChanges(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:507089 """Changes to GRD files must be consistent for tools to read them."""
7090 changed_grds = input_api.AffectedFiles(
7091 include_deletes=False,
7092 file_filter=lambda f: f.LocalPath().endswith(('.grd')))
7093 errors = []
7094 invalid_file_regexes = [(input_api.re.compile(matcher), msg)
7095 for matcher, msg in _INVALID_GRD_FILE_LINE]
7096 for grd in changed_grds:
7097 for i, line in enumerate(grd.NewContents()):
7098 for matcher, msg in invalid_file_regexes:
7099 if matcher.search(line):
7100 errors.append(
7101 output_api.PresubmitError(
7102 'Problem on {grd}:{i} - {msg}'.format(
7103 grd=grd.LocalPath(), i=i + 1, msg=msg)))
7104 return errors
7105
Kevin McNee967dd2d22021-11-15 16:09:297106
Henrique Ferreiro2a4b55942021-11-29 23:45:367107def CheckAssertAshOnlyCode(input_api, output_api):
7108 """Errors if a BUILD.gn file in an ash/ directory doesn't include
7109 assert(is_chromeos_ash).
7110 """
7111
7112 def FileFilter(affected_file):
7113 """Includes directories known to be Ash only."""
7114 return input_api.FilterSourceFile(
7115 affected_file,
7116 files_to_check=(
7117 r'^ash/.*BUILD\.gn', # Top-level src/ash/.
7118 r'.*/ash/.*BUILD\.gn'), # Any path component.
7119 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP))
7120
7121 errors = []
7122 pattern = input_api.re.compile(r'assert\(is_chromeos_ash')
Jameson Thies0ce669f2021-12-09 15:56:567123 for f in input_api.AffectedFiles(include_deletes=False,
7124 file_filter=FileFilter):
Henrique Ferreiro2a4b55942021-11-29 23:45:367125 if (not pattern.search(input_api.ReadFile(f))):
7126 errors.append(
7127 output_api.PresubmitError(
7128 'Please add assert(is_chromeos_ash) to %s. If that\'s not '
7129 'possible, please create and issue and add a comment such '
Alison Galed6b25fe2024-04-17 13:59:047130 'as:\n # TODO(crbug.com/XXX): add '
Henrique Ferreiro2a4b55942021-11-29 23:45:367131 'assert(is_chromeos_ash) when ...' % f.LocalPath()))
7132 return errors
Lukasz Anforowicz7016d05e2021-11-30 03:56:277133
7134
Kalvin Lee84ad17a2023-09-25 11:14:417135def _IsMiraclePtrDisallowed(input_api, affected_file):
Sam Maiera6e76d72022-02-11 21:43:507136 path = affected_file.LocalPath()
7137 if not _IsCPlusPlusFile(input_api, path):
7138 return False
7139
Kalvin Lee84ad17a2023-09-25 11:14:417140 # Renderer code is generally allowed to use MiraclePtr.
7141 # These directories, however, are specifically disallowed.
7142 if ("third_party/blink/renderer/core/" in path
7143 or "third_party/blink/renderer/platform/heap/" in path
7144 or "third_party/blink/renderer/platform/wtf/" in path):
Sam Maiera6e76d72022-02-11 21:43:507145 return True
7146
7147 # Blink's public/web API is only used/included by Renderer-only code. Note
7148 # that public/platform API may be used in non-Renderer processes (e.g. there
7149 # are some includes in code used by Utility, PDF, or Plugin processes).
7150 if "/blink/public/web/" in path:
7151 return True
7152
7153 # We assume that everything else may be used outside of Renderer processes.
Lukasz Anforowicz7016d05e2021-11-30 03:56:277154 return False
7155
Alison Galed6b25fe2024-04-17 13:59:047156# TODO(crbug.com/40206238): Remove these checks, once they are replaced
Lukasz Anforowicz7016d05e2021-11-30 03:56:277157# by the Chromium Clang Plugin (which will be preferable because it will
7158# 1) report errors earlier - at compile-time and 2) cover more rules).
7159def CheckRawPtrUsage(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:507160 """Rough checks that raw_ptr<T> usage guidelines are followed."""
7161 errors = []
7162 # The regex below matches "raw_ptr<" following a word boundary, but not in a
7163 # C++ comment.
7164 raw_ptr_matcher = input_api.re.compile(r'^((?!//).)*\braw_ptr<')
Kalvin Lee84ad17a2023-09-25 11:14:417165 file_filter = lambda f: _IsMiraclePtrDisallowed(input_api, f)
Sam Maiera6e76d72022-02-11 21:43:507166 for f, line_num, line in input_api.RightHandSideLines(file_filter):
7167 if raw_ptr_matcher.search(line):
7168 errors.append(
7169 output_api.PresubmitError(
7170 'Problem on {path}:{line} - '\
Kalvin Lee84ad17a2023-09-25 11:14:417171 'raw_ptr<T> should not be used in this renderer code '\
Sam Maiera6e76d72022-02-11 21:43:507172 '(as documented in the "Pointers to unprotected memory" '\
7173 'section in //base/memory/raw_ptr.md)'.format(
7174 path=f.LocalPath(), line=line_num)))
7175 return errors
Henrique Ferreirof9819f2e32021-11-30 13:31:567176
mikt9337567c2023-09-08 18:38:177177def CheckAdvancedMemorySafetyChecksUsage(input_api, output_api):
7178 """Checks that ADVANCED_MEMORY_SAFETY_CHECKS() macro is neither added nor
7179 removed as it is managed by the memory safety team internally.
7180 Do not add / remove it manually."""
7181 paths = set([])
7182 # The regex below matches "ADVANCED_MEMORY_SAFETY_CHECKS(" following a word
7183 # boundary, but not in a C++ comment.
7184 macro_matcher = input_api.re.compile(
7185 r'^((?!//).)*\bADVANCED_MEMORY_SAFETY_CHECKS\(', input_api.re.MULTILINE)
7186 for f in input_api.AffectedFiles():
7187 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
7188 continue
7189 if macro_matcher.search(f.GenerateScmDiff()):
7190 paths.add(f.LocalPath())
7191 if not paths:
7192 return []
7193 return [output_api.PresubmitPromptWarning(
7194 'ADVANCED_MEMORY_SAFETY_CHECKS() macro is managed by ' \
7195 'the memory safety team (chrome-memory-safety@). ' \
7196 'Please contact us to add/delete the uses of the macro.',
7197 paths)]
Henrique Ferreirof9819f2e32021-11-30 13:31:567198
7199def CheckPythonShebang(input_api, output_api):
7200 """Checks that python scripts use #!/usr/bin/env instead of hardcoding a
7201 system-wide python.
7202 """
7203 errors = []
7204 sources = lambda affected_file: input_api.FilterSourceFile(
7205 affected_file,
7206 files_to_skip=((_THIRD_PARTY_EXCEPT_BLINK,
7207 r'third_party/blink/web_tests/external/') + input_api.
7208 DEFAULT_FILES_TO_SKIP),
7209 files_to_check=[r'.*\.py$'])
7210 for f in input_api.AffectedSourceFiles(sources):
Takuto Ikuta36976512021-11-30 23:15:277211 for line_num, line in f.ChangedContents():
7212 if line_num == 1 and line.startswith('#!/usr/bin/python'):
7213 errors.append(f.LocalPath())
7214 break
Henrique Ferreirof9819f2e32021-11-30 13:31:567215
7216 result = []
7217 for file in errors:
7218 result.append(
7219 output_api.PresubmitError(
7220 "Please use '#!/usr/bin/env python/2/3' as the shebang of %s" %
7221 file))
7222 return result
James Shen81cc0e22022-06-15 21:10:457223
7224
7225def CheckBatchAnnotation(input_api, output_api):
7226 """Checks that tests have either @Batch or @DoNotBatch annotation. If this
7227 is not an instrumentation test, disregard."""
7228
7229 batch_annotation = input_api.re.compile(r'^\s*@Batch')
7230 do_not_batch_annotation = input_api.re.compile(r'^\s*@DoNotBatch')
7231 robolectric_test = input_api.re.compile(r'[rR]obolectric')
7232 test_class_declaration = input_api.re.compile(r'^\s*public\sclass.*Test')
7233 uiautomator_test = input_api.re.compile(r'[uU]i[aA]utomator')
Mark Schillaci8ef0d872023-07-18 22:07:597234 test_annotation_declaration = input_api.re.compile(r'^\s*public\s@interface\s.*{')
James Shen81cc0e22022-06-15 21:10:457235
ckitagawae8fd23b2022-06-17 15:29:387236 missing_annotation_errors = []
7237 extra_annotation_errors = []
James Shen81cc0e22022-06-15 21:10:457238
7239 def _FilterFile(affected_file):
7240 return input_api.FilterSourceFile(
7241 affected_file,
7242 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP,
7243 files_to_check=[r'.*Test\.java$'])
7244
7245 for f in input_api.AffectedSourceFiles(_FilterFile):
7246 batch_matched = None
7247 do_not_batch_matched = None
7248 is_instrumentation_test = True
Mark Schillaci8ef0d872023-07-18 22:07:597249 test_annotation_declaration_matched = None
James Shen81cc0e22022-06-15 21:10:457250 for line in f.NewContents():
7251 if robolectric_test.search(line) or uiautomator_test.search(line):
7252 # Skip Robolectric and UiAutomator tests.
7253 is_instrumentation_test = False
7254 break
7255 if not batch_matched:
7256 batch_matched = batch_annotation.search(line)
7257 if not do_not_batch_matched:
7258 do_not_batch_matched = do_not_batch_annotation.search(line)
7259 test_class_declaration_matched = test_class_declaration.search(
7260 line)
Mark Schillaci8ef0d872023-07-18 22:07:597261 test_annotation_declaration_matched = test_annotation_declaration.search(line)
7262 if test_class_declaration_matched or test_annotation_declaration_matched:
James Shen81cc0e22022-06-15 21:10:457263 break
Mark Schillaci8ef0d872023-07-18 22:07:597264 if test_annotation_declaration_matched:
7265 continue
James Shen81cc0e22022-06-15 21:10:457266 if (is_instrumentation_test and
7267 not batch_matched and
7268 not do_not_batch_matched):
Sam Maier4cef9242022-10-03 14:21:247269 missing_annotation_errors.append(str(f.LocalPath()))
ckitagawae8fd23b2022-06-17 15:29:387270 if (not is_instrumentation_test and
7271 (batch_matched or
7272 do_not_batch_matched)):
Sam Maier4cef9242022-10-03 14:21:247273 extra_annotation_errors.append(str(f.LocalPath()))
James Shen81cc0e22022-06-15 21:10:457274
7275 results = []
7276
ckitagawae8fd23b2022-06-17 15:29:387277 if missing_annotation_errors:
James Shen81cc0e22022-06-15 21:10:457278 results.append(
7279 output_api.PresubmitPromptWarning(
7280 """
Andrew Grieve43a5cf82023-09-08 15:09:467281A change was made to an on-device test that has neither been annotated with
7282@Batch nor @DoNotBatch. If this is a new test, please add the annotation. If
7283this is an existing test, please consider adding it if you are sufficiently
7284familiar with the test (but do so as a separate change).
7285
Jens Mueller2085ff82023-02-27 11:54:497286See https://source.chromium.org/chromium/chromium/src/+/main:docs/testing/batching_instrumentation_tests.md
ckitagawae8fd23b2022-06-17 15:29:387287""", missing_annotation_errors))
7288 if extra_annotation_errors:
7289 results.append(
7290 output_api.PresubmitPromptWarning(
7291 """
7292Robolectric tests do not need a @Batch or @DoNotBatch annotations.
7293""", extra_annotation_errors))
James Shen81cc0e22022-06-15 21:10:457294
7295 return results
Sam Maier4cef9242022-10-03 14:21:247296
7297
7298def CheckMockAnnotation(input_api, output_api):
7299 """Checks that we have annotated all Mockito.mock()-ed or Mockito.spy()-ed
7300 classes with @Mock or @Spy. If this is not an instrumentation test,
7301 disregard."""
7302
7303 # This is just trying to be approximately correct. We are not writing a
7304 # Java parser, so special cases like statically importing mock() then
7305 # calling an unrelated non-mockito spy() function will cause a false
7306 # positive.
7307 package_name = input_api.re.compile(r'^package\s+(\w+(?:\.\w+)+);')
7308 mock_static_import = input_api.re.compile(
7309 r'^import\s+static\s+org.mockito.Mockito.(?:mock|spy);')
7310 import_class = input_api.re.compile(r'import\s+((?:\w+\.)+)(\w+);')
7311 mock_annotation = input_api.re.compile(r'^\s*@(?:Mock|Spy)')
7312 field_type = input_api.re.compile(r'(\w+)(?:<\w+>)?\s+\w+\s*(?:;|=)')
7313 mock_or_spy_function_call = r'(?:mock|spy)\(\s*(?:new\s*)?(\w+)(?:\.class|\()'
7314 fully_qualified_mock_function = input_api.re.compile(
7315 r'Mockito\.' + mock_or_spy_function_call)
7316 statically_imported_mock_function = input_api.re.compile(
7317 r'\W' + mock_or_spy_function_call)
7318 robolectric_test = input_api.re.compile(r'[rR]obolectric')
7319 uiautomator_test = input_api.re.compile(r'[uU]i[aA]utomator')
7320
7321 def _DoClassLookup(class_name, class_name_map, package):
7322 found = class_name_map.get(class_name)
7323 if found is not None:
7324 return found
7325 else:
7326 return package + '.' + class_name
7327
7328 def _FilterFile(affected_file):
7329 return input_api.FilterSourceFile(
7330 affected_file,
7331 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP,
7332 files_to_check=[r'.*Test\.java$'])
7333
7334 mocked_by_function_classes = set()
7335 mocked_by_annotation_classes = set()
7336 class_to_filename = {}
7337 for f in input_api.AffectedSourceFiles(_FilterFile):
7338 mock_function_regex = fully_qualified_mock_function
7339 next_line_is_annotated = False
7340 fully_qualified_class_map = {}
7341 package = None
7342
7343 for line in f.NewContents():
7344 if robolectric_test.search(line) or uiautomator_test.search(line):
7345 # Skip Robolectric and UiAutomator tests.
7346 break
7347
7348 m = package_name.search(line)
7349 if m:
7350 package = m.group(1)
7351 continue
7352
7353 if mock_static_import.search(line):
7354 mock_function_regex = statically_imported_mock_function
7355 continue
7356
7357 m = import_class.search(line)
7358 if m:
7359 fully_qualified_class_map[m.group(2)] = m.group(1) + m.group(2)
7360 continue
7361
7362 if next_line_is_annotated:
7363 next_line_is_annotated = False
7364 fully_qualified_class = _DoClassLookup(
7365 field_type.search(line).group(1), fully_qualified_class_map,
7366 package)
7367 mocked_by_annotation_classes.add(fully_qualified_class)
7368 continue
7369
7370 if mock_annotation.search(line):
Sam Maierb8a66a02023-10-10 13:50:557371 field_type_search = field_type.search(line)
7372 if field_type_search:
7373 fully_qualified_class = _DoClassLookup(
7374 field_type_search.group(1), fully_qualified_class_map,
7375 package)
7376 mocked_by_annotation_classes.add(fully_qualified_class)
7377 else:
7378 next_line_is_annotated = True
Sam Maier4cef9242022-10-03 14:21:247379 continue
7380
7381 m = mock_function_regex.search(line)
7382 if m:
7383 fully_qualified_class = _DoClassLookup(m.group(1),
7384 fully_qualified_class_map, package)
7385 # Skipping builtin classes, since they don't get optimized.
7386 if fully_qualified_class.startswith(
7387 'android.') or fully_qualified_class.startswith(
7388 'java.'):
7389 continue
7390 class_to_filename[fully_qualified_class] = str(f.LocalPath())
7391 mocked_by_function_classes.add(fully_qualified_class)
7392
7393 results = []
7394 missed_classes = mocked_by_function_classes - mocked_by_annotation_classes
7395 if missed_classes:
7396 error_locations = []
7397 for c in missed_classes:
7398 error_locations.append(c + ' in ' + class_to_filename[c])
7399 results.append(
7400 output_api.PresubmitPromptWarning(
7401 """
7402Mockito.mock()/spy() cause issues with our Java optimizer. You have 3 options:
74031) If the mocked variable can be a class member, annotate the member with
7404 @Mock/@Spy.
74052) If the mocked variable cannot be a class member, create a dummy member
7406 variable of that type, annotated with @Mock/@Spy. This dummy does not need
7407 to be used or initialized in any way.
74083) If the mocked type is definitely not going to be optimized, whether it's a
7409 builtin type which we don't ship, or a class you know R8 will treat
7410 specially, you can ignore this warning.
7411""", error_locations))
7412
7413 return results
Mike Dougherty1b8be712022-10-20 00:15:137414
7415def CheckNoJsInIos(input_api, output_api):
7416 """Checks to make sure that JavaScript files are not used on iOS."""
7417
7418 def _FilterFile(affected_file):
7419 return input_api.FilterSourceFile(
7420 affected_file,
7421 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP +
Daniel White44b8bd02023-08-22 16:20:367422 (r'^ios/third_party/*', r'^ios/tools/*', r'^third_party/*',
7423 r'^components/autofill/ios/form_util/resources/*'),
Mike Dougherty1b8be712022-10-20 00:15:137424 files_to_check=[r'^ios/.*\.js$', r'.*/ios/.*\.js$'])
7425
Mike Dougherty4d1050b2023-03-14 15:59:537426 deleted_files = []
7427
7428 # Collect filenames of all removed JS files.
Arthur Sonzognic66e9c82024-04-23 07:53:047429 for f in input_api.AffectedFiles(file_filter=_FilterFile):
Mike Dougherty4d1050b2023-03-14 15:59:537430 local_path = f.LocalPath()
7431
7432 if input_api.os_path.splitext(local_path)[1] == '.js' and f.Action() == 'D':
7433 deleted_files.append(input_api.os_path.basename(local_path))
7434
Mike Dougherty1b8be712022-10-20 00:15:137435 error_paths = []
Mike Dougherty4d1050b2023-03-14 15:59:537436 moved_paths = []
Mike Dougherty1b8be712022-10-20 00:15:137437 warning_paths = []
7438
7439 for f in input_api.AffectedSourceFiles(_FilterFile):
7440 local_path = f.LocalPath()
7441
7442 if input_api.os_path.splitext(local_path)[1] == '.js':
7443 if f.Action() == 'A':
Mike Dougherty4d1050b2023-03-14 15:59:537444 if input_api.os_path.basename(local_path) in deleted_files:
7445 # This script was probably moved rather than newly created.
7446 # Present a warning instead of an error for these cases.
7447 moved_paths.append(local_path)
7448 else:
7449 error_paths.append(local_path)
Mike Dougherty1b8be712022-10-20 00:15:137450 elif f.Action() != 'D':
7451 warning_paths.append(local_path)
7452
7453 results = []
7454
7455 if warning_paths:
7456 results.append(output_api.PresubmitPromptWarning(
7457 'TypeScript is now fully supported for iOS feature scripts. '
7458 'Consider converting JavaScript files to TypeScript. See '
7459 '//ios/web/public/js_messaging/README.md for more details.',
7460 warning_paths))
7461
Mike Dougherty4d1050b2023-03-14 15:59:537462 if moved_paths:
7463 results.append(output_api.PresubmitPromptWarning(
7464 'Do not use JavaScript on iOS for new files as TypeScript is '
7465 'fully supported. (If this is a moved file, you may leave the '
7466 'script unconverted.) See //ios/web/public/js_messaging/README.md '
7467 'for help using scripts on iOS.', moved_paths))
7468
Mike Dougherty1b8be712022-10-20 00:15:137469 if error_paths:
7470 results.append(output_api.PresubmitError(
7471 'Do not use JavaScript on iOS as TypeScript is fully supported. '
7472 'See //ios/web/public/js_messaging/README.md for help using '
7473 'scripts on iOS.', error_paths))
7474
7475 return results
Hans Wennborg23a81d52023-03-24 16:38:137476
7477def CheckLibcxxRevisionsMatch(input_api, output_api):
7478 """Check to make sure the libc++ version matches across deps files."""
Andrew Grieve21bb6792023-03-27 19:06:487479 # Disable check for changes to sub-repositories.
7480 if input_api.PresubmitLocalPath() != input_api.change.RepositoryRoot():
Sam Maierb926c58c2023-08-08 19:58:257481 return []
Hans Wennborg23a81d52023-03-24 16:38:137482
7483 DEPS_FILES = [ 'DEPS', 'buildtools/deps_revisions.gni' ]
7484
7485 file_filter = lambda f: f.LocalPath().replace(
7486 input_api.os_path.sep, '/') in DEPS_FILES
7487 changed_deps_files = input_api.AffectedFiles(file_filter=file_filter)
7488 if not changed_deps_files:
7489 return []
7490
7491 def LibcxxRevision(file):
7492 file = input_api.os_path.join(input_api.PresubmitLocalPath(),
7493 *file.split('/'))
7494 return input_api.re.search(
7495 r'libcxx_revision.*[:=].*[\'"](\w+)[\'"]',
7496 input_api.ReadFile(file)).group(1)
7497
7498 if len(set([LibcxxRevision(f) for f in DEPS_FILES])) == 1:
7499 return []
7500
7501 return [output_api.PresubmitError(
7502 'libcxx_revision not equal across %s' % ', '.join(DEPS_FILES),
7503 changed_deps_files)]
Arthur Sonzogni7109bd32023-10-03 10:34:427504
7505
7506def CheckDanglingUntriaged(input_api, output_api):
7507 """Warn developers adding DanglingUntriaged raw_ptr."""
7508
7509 # Ignore during git presubmit --all.
7510 #
7511 # This would be too costly, because this would check every lines of every
7512 # C++ files. Check from _BANNED_CPP_FUNCTIONS are also reading the whole
7513 # source code, but only once to apply every checks. It seems the bots like
7514 # `win-presubmit` are particularly sensitive to reading the files. Adding
7515 # this check caused the bot to run 2x longer. See https://crbug.com/1486612.
7516 if input_api.no_diffs:
Arthur Sonzogni9eafd222023-11-10 08:50:397517 return []
Arthur Sonzogni7109bd32023-10-03 10:34:427518
7519 def FilterFile(file):
7520 return input_api.FilterSourceFile(
7521 file,
7522 files_to_check=[r".*\.(h|cc|cpp|cxx|m|mm)$"],
7523 files_to_skip=[r"^base/allocator.*"],
7524 )
7525
7526 count = 0
Arthur Sonzognic66e9c82024-04-23 07:53:047527 for f in input_api.AffectedFiles(file_filter=FilterFile):
Arthur Sonzogni9eafd222023-11-10 08:50:397528 count -= sum([l.count("DanglingUntriaged") for l in f.OldContents()])
7529 count += sum([l.count("DanglingUntriaged") for l in f.NewContents()])
Arthur Sonzogni7109bd32023-10-03 10:34:427530
7531 # Most likely, nothing changed:
7532 if count == 0:
7533 return []
7534
7535 # Congrats developers for improving it:
7536 if count < 0:
Arthur Sonzogni9eafd222023-11-10 08:50:397537 message = f"DanglingUntriaged pointers removed: {-count}\nThank you!"
Arthur Sonzogni7109bd32023-10-03 10:34:427538 return [output_api.PresubmitNotifyResult(message)]
7539
7540 # Check for 'DanglingUntriaged-notes' in the description:
7541 notes_regex = input_api.re.compile("DanglingUntriaged-notes[:=]")
7542 if any(
7543 notes_regex.match(line)
7544 for line in input_api.change.DescriptionText().splitlines()):
7545 return []
7546
7547 # Check for DanglingUntriaged-notes in the git footer:
7548 if input_api.change.GitFootersFromDescription().get(
7549 "DanglingUntriaged-notes", []):
7550 return []
7551
7552 message = (
Arthur Sonzogni9eafd222023-11-10 08:50:397553 "Unexpected new occurrences of `DanglingUntriaged` detected. Please\n" +
7554 "avoid adding new ones\n" +
7555 "\n" +
7556 "See documentation:\n" +
7557 "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md\n" +
7558 "\n" +
7559 "See also the guide to fix dangling pointers:\n" +
7560 "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr_guide.md\n" +
7561 "\n" +
7562 "To disable this warning, please add in the commit description:\n" +
Alex Gough26dcd852023-12-22 16:47:197563 "DanglingUntriaged-notes: <rationale for new untriaged dangling " +
Arthur Sonzogni9eafd222023-11-10 08:50:397564 "pointers>"
Arthur Sonzogni7109bd32023-10-03 10:34:427565 )
7566 return [output_api.PresubmitPromptWarning(message)]
Jan Keitel77be7522023-10-12 20:40:497567
7568def CheckInlineConstexprDefinitionsInHeaders(input_api, output_api):
7569 """Checks that non-static constexpr definitions in headers are inline."""
7570 # In a properly formatted file, constexpr definitions inside classes or
7571 # structs will have additional whitespace at the beginning of the line.
7572 # The pattern looks for variables initialized as constexpr kVar = ...; or
7573 # constexpr kVar{...};
7574 # The pattern does not match expressions that have braces in kVar to avoid
7575 # matching constexpr functions.
7576 pattern = input_api.re.compile(r'^constexpr (?!inline )[^\(\)]*[={]')
7577 attribute_pattern = input_api.re.compile(r'(\[\[[a-zA-Z_:]+\]\]|[A-Z]+[A-Z_]+) ')
7578 problems = []
7579 for f in input_api.AffectedFiles():
7580 if not _IsCPlusPlusHeaderFile(input_api, f.LocalPath()):
7581 continue
7582
7583 for line_number, line in f.ChangedContents():
7584 line = attribute_pattern.sub('', line)
7585 if pattern.search(line):
7586 problems.append(
7587 f"{f.LocalPath()}: {line_number}\n {line}")
7588
7589 if problems:
7590 return [
7591 output_api.PresubmitPromptWarning(
7592 'Consider inlining constexpr variable definitions in headers '
7593 'outside of classes to avoid unnecessary copies of the '
7594 'constant. See https://abseil.io/tips/168 for more details.',
7595 problems)
7596 ]
7597 else:
7598 return []
Alison Galed6b25fe2024-04-17 13:59:047599
7600def CheckTodoBugReferences(input_api, output_api):
7601 """Checks that bugs in TODOs use updated issue tracker IDs."""
7602
7603 files_to_skip = ['PRESUBMIT_test.py']
7604
7605 def _FilterFile(affected_file):
7606 return input_api.FilterSourceFile(
7607 affected_file,
7608 files_to_skip=files_to_skip)
7609
7610 # Monorail bug IDs are all less than or equal to 1524553 so check that all
7611 # bugs in TODOs are greater than that value.
7612 pattern = input_api.re.compile(r'.*TODO\([^\)0-9]*([0-9]+)\).*')
7613 problems = []
7614 for f in input_api.AffectedSourceFiles(_FilterFile):
7615 for line_number, line in f.ChangedContents():
7616 match = pattern.match(line)
7617 if match and int(match.group(1)) <= 1524553:
7618 problems.append(
7619 f"{f.LocalPath()}: {line_number}\n {line}")
7620
7621 if problems:
7622 return [
7623 output_api.PresubmitPromptWarning(
Alison Galecb598de52024-04-26 17:03:257624 'TODOs should use the new Chromium Issue Tracker IDs which can '
7625 'be found by navigating to the bug. See '
7626 'https://crbug.com/336778624 for more details.',
Alison Galed6b25fe2024-04-17 13:59:047627 problems)
7628 ]
7629 else:
7630 return []