blob: 1215dc24556b8e38938d1ee2f9d98762e44b5859 [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,
[email protected]06e6d0ff2012-12-11 01:36:4483 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
James Cook1b4dc132021-03-09 22:45:1384 # Test suite files, like:
85 # foo_browsertest.cc
86 # bar_unittest_mac.cc (suffix)
87 # baz_unittests.cc (plural)
88 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(s)?(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1289 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1890 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
Victor Hugo Vianna Silvac22e0202021-06-09 19:46:2191 r'.+sync_service_impl_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Bruce Dawson40fece62022-09-16 19:58:3192 r'.*/(test|tool(s)?)/.*',
danakj89f47082020-09-02 17:53:4393 # content_shell is used for running content_browsertests.
Bruce Dawson40fece62022-09-16 19:58:3194 r'content/shell/.*',
danakj89f47082020-09-02 17:53:4395 # Web test harness.
Bruce Dawson40fece62022-09-16 19:58:3196 r'content/web_test/.*',
[email protected]7b054982013-11-27 00:44:4797 # Non-production example code.
Bruce Dawson40fece62022-09-16 19:58:3198 r'mojo/examples/.*',
[email protected]8176de12014-06-20 19:07:0899 # Launcher for running iOS tests on the simulator.
Bruce Dawson40fece62022-09-16 19:58:31100 r'testing/iossim/iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:41101 # EarlGrey app side code for tests.
Bruce Dawson40fece62022-09-16 19:58:31102 r'ios/.*_app_interface\.mm$',
Allen Bauer0678d772020-05-11 22:25:17103 # Views Examples code
Bruce Dawson40fece62022-09-16 19:58:31104 r'ui/views/examples/.*',
Austin Sullivan33da70a2020-10-07 15:39:41105 # Chromium Codelab
Bruce Dawson40fece62022-09-16 19:58:31106 r'codelabs/*'
[email protected]06e6d0ff2012-12-11 01:36:44107)
[email protected]ca8d1982009-02-19 16:33:12108
Daniel Bratell609102be2019-03-27 20:53:21109_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:15110
[email protected]eea609a2011-11-18 13:10:12111_TEST_ONLY_WARNING = (
112 'You might be calling functions intended only for testing from\n'
danakj5f6e3b82020-09-10 13:52:55113 'production code. If you are doing this from inside another method\n'
114 'named as *ForTesting(), then consider exposing things to have tests\n'
115 'make that same call directly.\n'
116 'If that is not possible, you may put a comment on the same line with\n'
117 ' // IN-TEST \n'
118 'to tell the PRESUBMIT script that the code is inside a *ForTesting()\n'
119 'method and can be ignored. Do not do this inside production code.\n'
120 'The android-binary-size trybot will block if the method exists in the\n'
Yulun Zeng08d7d8c2024-02-01 18:46:54121 'release apk.\n'
122 'Note: this warning might be a false positive (crbug.com/1196548).')
[email protected]eea609a2011-11-18 13:10:12123
124
Daniel Chenga44a1bcd2022-03-15 20:00:15125@dataclass
126class BanRule:
Daniel Chenga37c03db2022-05-12 17:20:34127 # String pattern. If the pattern begins with a slash, the pattern will be
128 # treated as a regular expression instead.
129 pattern: str
130 # Explanation as a sequence of strings. Each string in the sequence will be
131 # printed on its own line.
132 explanation: Sequence[str]
133 # Whether or not to treat this ban as a fatal error. If unspecified,
134 # defaults to true.
135 treat_as_error: Optional[bool] = None
136 # Paths that should be excluded from the ban check. Each string is a regular
137 # expression that will be matched against the path of the file being checked
138 # relative to the root of the source tree.
139 excluded_paths: Optional[Sequence[str]] = None
[email protected]cf9b78f2012-11-14 11:40:28140
Daniel Chenga44a1bcd2022-03-15 20:00:15141
Daniel Cheng917ce542022-03-15 20:46:57142_BANNED_JAVA_IMPORTS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15143 BanRule(
144 'import java.net.URI;',
145 (
146 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
147 ),
148 excluded_paths=(
149 (r'net/android/javatests/src/org/chromium/net/'
150 'AndroidProxySelectorTest\.java'),
151 r'components/cronet/',
152 r'third_party/robolectric/local/',
153 ),
Michael Thiessen44457642020-02-06 00:24:15154 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15155 BanRule(
156 'import android.annotation.TargetApi;',
157 (
158 'Do not use TargetApi, use @androidx.annotation.RequiresApi instead. '
159 'RequiresApi ensures that any calls are guarded by the appropriate '
160 'SDK_INT check. See https://crbug.com/1116486.',
161 ),
162 ),
163 BanRule(
Mohamed Heikal3d7a94c2023-03-28 16:55:24164 'import androidx.test.rule.UiThreadTestRule;',
Daniel Chenga44a1bcd2022-03-15 20:00:15165 (
166 'Do not use UiThreadTestRule, just use '
167 '@org.chromium.base.test.UiThreadTest on test methods that should run '
168 'on the UI thread. See https://crbug.com/1111893.',
169 ),
170 ),
171 BanRule(
Mohamed Heikal3d7a94c2023-03-28 16:55:24172 'import androidx.test.annotation.UiThreadTest;',
173 ('Do not use androidx.test.annotation.UiThreadTest, use '
Daniel Chenga44a1bcd2022-03-15 20:00:15174 'org.chromium.base.test.UiThreadTest instead. See '
175 'https://crbug.com/1111893.',
176 ),
177 ),
178 BanRule(
Mohamed Heikal3d7a94c2023-03-28 16:55:24179 'import androidx.test.rule.ActivityTestRule;',
Daniel Chenga44a1bcd2022-03-15 20:00:15180 (
181 'Do not use ActivityTestRule, use '
182 'org.chromium.base.test.BaseActivityTestRule instead.',
183 ),
184 excluded_paths=(
185 'components/cronet/',
186 ),
187 ),
Min Qinbc44383c2023-02-22 17:25:26188 BanRule(
189 'import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;',
190 (
191 'Do not use VectorDrawableCompat, use getResources().getDrawable() to '
192 'avoid extra indirections. Please also add trace event as the call '
193 'might take more than 20 ms to complete.',
194 ),
195 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15196)
wnwenbdc444e2016-05-25 13:44:15197
Daniel Cheng917ce542022-03-15 20:46:57198_BANNED_JAVA_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15199 BanRule(
Eric Stevensona9a980972017-09-23 00:04:41200 'StrictMode.allowThreadDiskReads()',
201 (
202 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
203 'directly.',
204 ),
205 False,
206 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15207 BanRule(
Eric Stevensona9a980972017-09-23 00:04:41208 'StrictMode.allowThreadDiskWrites()',
209 (
210 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
211 'directly.',
212 ),
213 False,
214 ),
Daniel Cheng917ce542022-03-15 20:46:57215 BanRule(
Michael Thiessen0f2547e2020-07-27 21:55:36216 '.waitForIdleSync()',
217 (
218 'Do not use waitForIdleSync as it masks underlying issues. There is '
219 'almost always something else you should wait on instead.',
220 ),
221 False,
222 ),
Ashley Newson09cbd602022-10-26 11:40:14223 BanRule(
Ashley Newsoneb6f5ce2022-10-26 14:45:42224 r'/(?<!\bsuper\.)(?<!\bIntent )\bregisterReceiver\(',
Ashley Newson09cbd602022-10-26 11:40:14225 (
226 'Do not call android.content.Context.registerReceiver (or an override) '
227 'directly. Use one of the wrapper methods defined in '
228 'org.chromium.base.ContextUtils, such as '
229 'registerProtectedBroadcastReceiver, '
230 'registerExportedBroadcastReceiver, or '
231 'registerNonExportedBroadcastReceiver. See their documentation for '
232 'which one to use.',
233 ),
234 True,
235 excluded_paths=(
Ashley Newson22bc26d2022-11-01 20:30:57236 r'.*Test[^a-z]',
237 r'third_party/',
Ashley Newson09cbd602022-10-26 11:40:14238 'base/android/java/src/org/chromium/base/ContextUtils.java',
Brandon Mousseau7e76a9c2022-12-08 22:08:38239 'chromecast/browser/android/apk/src/org/chromium/chromecast/shell/BroadcastReceiverScope.java',
Ashley Newson09cbd602022-10-26 11:40:14240 ),
241 ),
Ted Chocd5b327b12022-11-05 02:13:22242 BanRule(
243 r'/(?:extends|new)\s*(?:android.util.)?Property<[A-Za-z.]+,\s*(?:Integer|Float)>',
244 (
245 'Do not use Property<..., Integer|Float>, but use FloatProperty or '
246 'IntProperty because it will avoid unnecessary autoboxing of '
247 'primitives.',
248 ),
249 ),
Peilin Wangbba4a8652022-11-10 16:33:57250 BanRule(
251 'requestLayout()',
252 (
253 'Layouts can be expensive. Prefer using ViewUtils.requestLayout(), '
254 'which emits a trace event with additional information to help with '
255 'scroll jank investigations. See http://crbug.com/1354176.',
256 ),
257 False,
258 excluded_paths=(
259 'ui/android/java/src/org/chromium/ui/base/ViewUtils.java',
260 ),
261 ),
Ted Chocf40ea9152023-02-14 19:02:39262 BanRule(
Ted Chocf486e3f2024-02-17 05:37:03263 'ProfileManager.getLastUsedRegularProfile()',
Ted Chocf40ea9152023-02-14 19:02:39264 (
265 'Prefer passing in the Profile reference instead of relying on the '
266 'static getLastUsedRegularProfile() call. Only top level entry points '
267 '(e.g. Activities) should call this method. Otherwise, the Profile '
268 'should either be passed in explicitly or retreived from an existing '
269 'entity with a reference to the Profile (e.g. WebContents).',
270 ),
271 False,
272 excluded_paths=(
273 r'.*Test[A-Z]?.*\.java',
274 ),
275 ),
Min Qinbc44383c2023-02-22 17:25:26276 BanRule(
277 r'/(ResourcesCompat|getResources\(\))\.getDrawable\(\)',
278 (
279 'getDrawable() can be expensive. If you have a lot of calls to '
280 'GetDrawable() or your code may introduce janks, please put your calls '
281 'inside a trace().',
282 ),
283 False,
284 excluded_paths=(
285 r'.*Test[A-Z]?.*\.java',
286 ),
287 ),
Henrique Nakashimabbf2b262023-03-10 17:21:39288 BanRule(
289 r'/RecordHistogram\.getHistogram(ValueCount|TotalCount|Samples)ForTesting\(',
290 (
291 'Raw histogram counts are easy to misuse; for example they don\'t reset '
Thiago Perrotta099034f2023-06-05 18:10:20292 'between batched tests. Use HistogramWatcher to check histogram records '
293 'instead.',
Henrique Nakashimabbf2b262023-03-10 17:21:39294 ),
295 False,
296 excluded_paths=(
297 'base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java',
298 'base/test/android/javatests/src/org/chromium/base/test/util/HistogramWatcher.java',
299 ),
300 ),
Eric Stevensona9a980972017-09-23 00:04:41301)
302
Clement Yan9b330cb2022-11-17 05:25:29303_BANNED_JAVASCRIPT_FUNCTIONS : Sequence [BanRule] = (
304 BanRule(
305 r'/\bchrome\.send\b',
306 (
307 '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).',
308 'Please use mojo instead for new webuis. https://docs.google.com/document/d/1RF-GSUoveYa37eoyZ9EhwMtaIwoW7Z88pIgNZ9YzQi4/edit#heading=h.gkk22wgk6wff',
309 ),
310 True,
311 (
312 r'^(?!ash\/webui).+',
313 # TODO(crbug.com/1385601): pre-existing violations still need to be
314 # cleaned up.
Rebekah Potter57aa94df2022-12-13 20:30:58315 'ash/webui/common/resources/cr.m.js',
Clement Yan9b330cb2022-11-17 05:25:29316 'ash/webui/common/resources/multidevice_setup/multidevice_setup_browser_proxy.js',
Martin Bidlingmaiera921fee72023-06-03 07:52:22317 'ash/webui/common/resources/quick_unlock/lock_screen_constants.ts',
Clement Yan9b330cb2022-11-17 05:25:29318 'ash/webui/common/resources/smb_shares/smb_browser_proxy.js',
Chad Duffin06e47de2023-12-14 18:04:13319 'ash/webui/connectivity_diagnostics/resources/connectivity_diagnostics.ts',
Clement Yan9b330cb2022-11-17 05:25:29320 'ash/webui/diagnostics_ui/resources/diagnostics_browser_proxy.ts',
321 'ash/webui/multidevice_debug/resources/logs.js',
322 'ash/webui/multidevice_debug/resources/webui.js',
323 'ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js',
324 'ash/webui/projector_app/resources/app/trusted/projector_browser_proxy.js',
Ashley Prasad71f9024e2023-09-25 22:33:55325 # TODO(b/301634378): Remove violation exception once Scanning App
326 # migrated off usage of `chrome.send`.
327 'ash/webui/scanning/resources/scanning_browser_proxy.ts',
Clement Yan9b330cb2022-11-17 05:25:29328 ),
329 ),
330)
331
Daniel Cheng917ce542022-03-15 20:46:57332_BANNED_OBJC_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15333 BanRule(
[email protected]127f18ec2012-06-16 05:05:59334 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20335 (
336 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59337 'prohibited. Please use CrTrackingArea instead.',
338 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
339 ),
340 False,
341 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15342 BanRule(
[email protected]eaae1972014-04-16 04:17:26343 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20344 (
345 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59346 'instead.',
347 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
348 ),
349 False,
350 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15351 BanRule(
[email protected]127f18ec2012-06-16 05:05:59352 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20353 (
354 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59355 'Please use |convertPoint:(point) fromView:nil| instead.',
356 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
357 ),
358 True,
359 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15360 BanRule(
[email protected]127f18ec2012-06-16 05:05:59361 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20362 (
363 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59364 'Please use |convertPoint:(point) toView:nil| instead.',
365 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
366 ),
367 True,
368 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15369 BanRule(
[email protected]127f18ec2012-06-16 05:05:59370 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20371 (
372 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59373 'Please use |convertRect:(point) fromView:nil| instead.',
374 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
375 ),
376 True,
377 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15378 BanRule(
[email protected]127f18ec2012-06-16 05:05:59379 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20380 (
381 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59382 'Please use |convertRect:(point) toView:nil| instead.',
383 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
384 ),
385 True,
386 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15387 BanRule(
[email protected]127f18ec2012-06-16 05:05:59388 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20389 (
390 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59391 'Please use |convertSize:(point) fromView:nil| instead.',
392 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
393 ),
394 True,
395 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15396 BanRule(
[email protected]127f18ec2012-06-16 05:05:59397 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20398 (
399 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59400 'Please use |convertSize:(point) toView:nil| instead.',
401 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
402 ),
403 True,
404 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15405 BanRule(
jif65398702016-10-27 10:19:48406 r"/\s+UTF8String\s*]",
407 (
408 'The use of -[NSString UTF8String] is dangerous as it can return null',
409 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
410 'Please use |SysNSStringToUTF8| instead.',
411 ),
412 True,
Marijn Kruisselbrink1b7c48952023-08-31 16:58:34413 excluded_paths = (
414 '^third_party/ocmock/OCMock/',
415 ),
jif65398702016-10-27 10:19:48416 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15417 BanRule(
Sylvain Defresne4cf1d182017-09-18 14:16:34418 r'__unsafe_unretained',
419 (
420 'The use of __unsafe_unretained is almost certainly wrong, unless',
421 'when interacting with NSFastEnumeration or NSInvocation.',
422 'Please use __weak in files build with ARC, nothing otherwise.',
423 ),
424 False,
425 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15426 BanRule(
Avi Drissman7382afa02019-04-29 23:27:13427 'freeWhenDone:NO',
428 (
429 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
430 'Foundation types is prohibited.',
431 ),
432 True,
433 ),
Avi Drissman3d243a42023-08-01 16:53:59434 BanRule(
435 'This file requires ARC support.',
436 (
437 'ARC compilation is default in Chromium; do not add boilerplate to ',
438 'files that require ARC.',
439 ),
440 True,
441 ),
[email protected]127f18ec2012-06-16 05:05:59442)
443
Sylvain Defresnea8b73d252018-02-28 15:45:54444_BANNED_IOS_OBJC_FUNCTIONS = (
Daniel Chenga44a1bcd2022-03-15 20:00:15445 BanRule(
Sylvain Defresnea8b73d252018-02-28 15:45:54446 r'/\bTEST[(]',
447 (
448 'TEST() macro should not be used in Objective-C++ code as it does not ',
449 'drain the autorelease pool at the end of the test. Use TEST_F() ',
450 'macro instead with a fixture inheriting from PlatformTest (or a ',
451 'typedef).'
452 ),
453 True,
454 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15455 BanRule(
Sylvain Defresnea8b73d252018-02-28 15:45:54456 r'/\btesting::Test\b',
457 (
458 'testing::Test should not be used in Objective-C++ code as it does ',
459 'not drain the autorelease pool at the end of the test. Use ',
460 'PlatformTest instead.'
461 ),
462 True,
463 ),
Ewann2ecc8d72022-07-18 07:41:23464 BanRule(
465 ' systemImageNamed:',
466 (
467 '+[UIImage systemImageNamed:] should not be used to create symbols.',
468 'Instead use a wrapper defined in:',
Victor Vianna77a40f62023-01-31 19:04:53469 'ios/chrome/browser/ui/icons/symbol_helpers.h'
Ewann2ecc8d72022-07-18 07:41:23470 ),
471 True,
Ewann450a2ef2022-07-19 14:38:23472 excluded_paths=(
Gauthier Ambard4d8756b2023-04-07 17:26:41473 'ios/chrome/browser/shared/ui/symbols/symbol_helpers.mm',
Gauthier Ambardd36c10b12023-03-16 08:45:03474 'ios/chrome/search_widget_extension/',
Ewann450a2ef2022-07-19 14:38:23475 ),
Ewann2ecc8d72022-07-18 07:41:23476 ),
Sylvain Defresnea8b73d252018-02-28 15:45:54477)
478
Daniel Cheng917ce542022-03-15 20:46:57479_BANNED_IOS_EGTEST_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15480 BanRule(
Peter K. Lee6c03ccff2019-07-15 14:40:05481 r'/\bEXPECT_OCMOCK_VERIFY\b',
482 (
483 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
484 'it is meant for GTests. Use [mock verify] instead.'
485 ),
486 True,
487 ),
488)
489
Daniel Cheng917ce542022-03-15 20:46:57490_BANNED_CPP_FUNCTIONS : Sequence[BanRule] = (
Daniel Chenga44a1bcd2022-03-15 20:00:15491 BanRule(
Peter Kasting7c0d98a2023-10-06 15:42:39492 '%#0',
493 (
494 'Zero-padded values that use "#" to add prefixes don\'t exhibit ',
495 'consistent behavior, since the prefix is not prepended for zero ',
496 'values. Use "0x%0..." instead.',
497 ),
498 False,
499 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
500 ),
501 BanRule(
Peter Kasting94a56c42019-10-25 21:54:04502 r'/\busing namespace ',
503 (
504 'Using directives ("using namespace x") are banned by the Google Style',
505 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
506 'Explicitly qualify symbols or use using declarations ("using x::foo").',
507 ),
508 True,
509 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
510 ),
Antonio Gomes07300d02019-03-13 20:59:57511 # Make sure that gtest's FRIEND_TEST() macro is not used; the
512 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
513 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
Daniel Chenga44a1bcd2022-03-15 20:00:15514 BanRule(
[email protected]23e6cbc2012-06-16 18:51:20515 'FRIEND_TEST(',
516 (
[email protected]e3c945502012-06-26 20:01:49517 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20518 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
519 ),
520 False,
Arthur Sonzogni19aa4922023-08-28 17:28:59521 excluded_paths = (
522 "base/gtest_prod_util.h",
Arthur Sonzogni0bcc0232023-10-03 08:48:32523 "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/gtest_prod_util.h",
Arthur Sonzogni19aa4922023-08-28 17:28:59524 ),
[email protected]23e6cbc2012-06-16 18:51:20525 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15526 BanRule(
tomhudsone2c14d552016-05-26 17:07:46527 'setMatrixClip',
528 (
529 'Overriding setMatrixClip() is prohibited; ',
530 'the base function is deprecated. ',
531 ),
532 True,
533 (),
534 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15535 BanRule(
[email protected]52657f62013-05-20 05:30:31536 'SkRefPtr',
537 (
538 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22539 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31540 ),
541 True,
542 (),
543 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15544 BanRule(
[email protected]52657f62013-05-20 05:30:31545 'SkAutoRef',
546 (
547 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22548 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31549 ),
550 True,
551 (),
552 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15553 BanRule(
[email protected]52657f62013-05-20 05:30:31554 'SkAutoTUnref',
555 (
556 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22557 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31558 ),
559 True,
560 (),
561 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15562 BanRule(
[email protected]52657f62013-05-20 05:30:31563 'SkAutoUnref',
564 (
565 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
566 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22567 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31568 ),
569 True,
570 (),
571 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15572 BanRule(
[email protected]d89eec82013-12-03 14:10:59573 r'/HANDLE_EINTR\(.*close',
574 (
575 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
576 'descriptor will be closed, and it is incorrect to retry the close.',
577 'Either call close directly and ignore its return value, or wrap close',
578 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
579 ),
580 True,
581 (),
582 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15583 BanRule(
[email protected]d89eec82013-12-03 14:10:59584 r'/IGNORE_EINTR\((?!.*close)',
585 (
586 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
587 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
588 ),
589 True,
590 (
591 # Files that #define IGNORE_EINTR.
Bruce Dawson40fece62022-09-16 19:58:31592 r'^base/posix/eintr_wrapper\.h$',
593 r'^ppapi/tests/test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59594 ),
595 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15596 BanRule(
[email protected]ec5b3f02014-04-04 18:43:43597 r'/v8::Extension\(',
598 (
599 'Do not introduce new v8::Extensions into the code base, use',
600 'gin::Wrappable instead. See http://crbug.com/334679',
601 ),
602 True,
[email protected]f55c90ee62014-04-12 00:50:03603 (
Bruce Dawson40fece62022-09-16 19:58:31604 r'extensions/renderer/safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03605 ),
[email protected]ec5b3f02014-04-04 18:43:43606 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15607 BanRule(
jame2d1a952016-04-02 00:27:10608 '#pragma comment(lib,',
609 (
610 'Specify libraries to link with in build files and not in the source.',
611 ),
612 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41613 (
Bruce Dawson40fece62022-09-16 19:58:31614 r'^base/third_party/symbolize/.*',
615 r'^third_party/abseil-cpp/.*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41616 ),
jame2d1a952016-04-02 00:27:10617 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15618 BanRule(
Gabriel Charette7cc6c432018-04-25 20:52:02619 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59620 (
621 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
622 ),
623 False,
624 (),
625 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15626 BanRule(
Gabriel Charette7cc6c432018-04-25 20:52:02627 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59628 (
629 'Consider using THREAD_CHECKER macros instead of the class directly.',
630 ),
631 False,
632 (),
633 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15634 BanRule(
Sean Maher03efef12022-09-23 22:43:13635 r'/\b(?!(Sequenced|SingleThread))\w*TaskRunner::(GetCurrentDefault|CurrentDefaultHandle)',
636 (
637 'It is not allowed to call these methods from the subclasses ',
638 'of Sequenced or SingleThread task runners.',
639 ),
640 True,
641 (),
642 ),
643 BanRule(
Yuri Wiitala2f8de5c2017-07-21 00:11:06644 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
645 (
646 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
647 'deprecated (http://crbug.com/634507). Please avoid converting away',
648 'from the Time types in Chromium code, especially if any math is',
649 'being done on time values. For interfacing with platform/library',
Peter Kasting8a2605652023-09-14 03:57:15650 'APIs, use base::Time::(From,To)DeltaSinceWindowsEpoch() or',
651 'base::{TimeDelta::In}Microseconds(), or one of the other type',
652 'converter methods instead. For faking TimeXXX values (for unit',
Peter Kasting53fd6ee2021-10-05 20:40:48653 'testing only), use TimeXXX() + Microseconds(N). For',
Yuri Wiitala2f8de5c2017-07-21 00:11:06654 'other use cases, please contact base/time/OWNERS.',
655 ),
656 False,
Arthur Sonzogni19aa4922023-08-28 17:28:59657 excluded_paths = (
658 "base/time/time.h",
Arthur Sonzogni0bcc0232023-10-03 08:48:32659 "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h",
Arthur Sonzogni19aa4922023-08-28 17:28:59660 ),
Yuri Wiitala2f8de5c2017-07-21 00:11:06661 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15662 BanRule(
dbeamb6f4fde2017-06-15 04:03:06663 'CallJavascriptFunctionUnsafe',
664 (
665 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
666 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
667 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
668 ),
669 False,
670 (
Bruce Dawson40fece62022-09-16 19:58:31671 r'^content/browser/webui/web_ui_impl\.(cc|h)$',
672 r'^content/public/browser/web_ui\.h$',
673 r'^content/public/test/test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06674 ),
675 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15676 BanRule(
dskiba1474c2bfd62017-07-20 02:19:24677 'leveldb::DB::Open',
678 (
679 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
680 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
681 "Chrome's tracing, making their memory usage visible.",
682 ),
683 True,
684 (
685 r'^third_party/leveldatabase/.*\.(cc|h)$',
686 ),
Gabriel Charette0592c3a2017-07-26 12:02:04687 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15688 BanRule(
Chris Mumfordc38afb62017-10-09 17:55:08689 'leveldb::NewMemEnv',
690 (
691 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58692 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
693 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08694 ),
695 True,
696 (
697 r'^third_party/leveldatabase/.*\.(cc|h)$',
698 ),
699 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15700 BanRule(
Gabriel Charetted9839bc2017-07-29 14:17:47701 'RunLoop::QuitCurrent',
702 (
Robert Liao64b7ab22017-08-04 23:03:43703 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
704 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47705 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41706 False,
Gabriel Charetted9839bc2017-07-29 14:17:47707 (),
Gabriel Charettea44975052017-08-21 23:14:04708 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15709 BanRule(
Gabriel Charettea44975052017-08-21 23:14:04710 'base::ScopedMockTimeMessageLoopTaskRunner',
711 (
Gabriel Charette87cc1af2018-04-25 20:52:51712 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11713 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51714 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
715 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
716 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04717 ),
Gabriel Charette87cc1af2018-04-25 20:52:51718 False,
Gabriel Charettea44975052017-08-21 23:14:04719 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57720 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15721 BanRule(
Dave Tapuska98199b612019-07-10 13:30:44722 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57723 (
724 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02725 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57726 ),
727 True,
Robert Ogden4c43a712023-06-28 22:03:19728 [
729 # Abseil's benchmarks never linked into chrome.
730 'third_party/abseil-cpp/.*_benchmark.cc',
Robert Ogden4c43a712023-06-28 22:03:19731 ],
Francois Doray43670e32017-09-27 12:40:38732 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15733 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:08734 r'/\bstd::sto(i|l|ul|ll|ull)\b',
Peter Kasting991618a62019-06-17 22:00:09735 (
Peter Kastinge2c5ee82023-02-15 17:23:08736 'std::sto{i,l,ul,ll,ull}() use exceptions to communicate results. ',
737 'Use base::StringTo[U]Int[64]() instead.',
Peter Kasting991618a62019-06-17 22:00:09738 ),
739 True,
740 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
741 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15742 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:08743 r'/\bstd::sto(f|d|ld)\b',
Peter Kasting991618a62019-06-17 22:00:09744 (
Peter Kastinge2c5ee82023-02-15 17:23:08745 'std::sto{f,d,ld}() use exceptions to communicate results. ',
Peter Kasting991618a62019-06-17 22:00:09746 'For locale-independent values, e.g. reading numbers from disk',
747 'profiles, use base::StringToDouble().',
748 'For user-visible values, parse using ICU.',
749 ),
750 True,
751 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
752 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15753 BanRule(
Daniel Bratell69334cc2019-03-26 11:07:45754 r'/\bstd::to_string\b',
755 (
Peter Kastinge2c5ee82023-02-15 17:23:08756 'std::to_string() is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09757 'For locale-independent strings, e.g. writing numbers to disk',
758 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45759 'For user-visible strings, use base::FormatNumber() and',
760 'the related functions in base/i18n/number_formatting.h.',
761 ),
Peter Kasting991618a62019-06-17 22:00:09762 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21763 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45764 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15765 BanRule(
Peter Kasting6f79b202023-08-09 21:25:41766 r'/#include <(cctype|ctype\.h|cwctype|wctype.h)>',
767 (
768 '<cctype>/<ctype.h>/<cwctype>/<wctype.h> are banned. Use',
769 '"third_party/abseil-cpp/absl/strings/ascii.h" instead.',
770 ),
771 True,
772 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
773 ),
774 BanRule(
Daniel Bratell69334cc2019-03-26 11:07:45775 r'/\bstd::shared_ptr\b',
776 (
Peter Kastinge2c5ee82023-02-15 17:23:08777 'std::shared_ptr is banned. Use scoped_refptr instead.',
Daniel Bratell69334cc2019-03-26 11:07:45778 ),
779 True,
Ulan Degenbaev947043882021-02-10 14:02:31780 [
781 # Needed for interop with third-party library.
782 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
Alex Chau9eb03cdd52020-07-13 21:04:57783 'array_buffer_contents\.(cc|h)',
Ben Kelly39bf6bef2021-10-04 22:54:58784 '^third_party/blink/renderer/bindings/core/v8/' +
785 'v8_wasm_response_extensions.cc',
Wez5f56be52021-05-04 09:30:58786 '^gin/array_buffer\.(cc|h)',
Jiahe Zhange97ba772023-07-27 02:46:41787 '^gin/per_isolate_data\.(cc|h)',
Wez5f56be52021-05-04 09:30:58788 '^chrome/services/sharing/nearby/',
Stephen Nuskoe09c8ef22022-09-29 00:47:28789 # Needed for interop with third-party library libunwindstack.
Stephen Nuskoe51c1382022-09-26 15:49:03790 '^base/profiler/libunwindstack_unwinder_android\.(cc|h)',
Thiabaud Engelbrecht42e09812023-08-29 21:19:30791 '^base/profiler/native_unwinder_android_memory_regions_map_impl.(cc|h)',
Bob Beck03509d282022-12-07 21:49:05792 # Needed for interop with third-party boringssl cert verifier
793 '^third_party/boringssl/',
794 '^net/cert/',
795 '^net/tools/cert_verify_tool/',
796 '^services/cert_verifier/',
797 '^components/certificate_transparency/',
798 '^components/media_router/common/providers/cast/certificate/',
Meilin Wang00efc7c2021-05-13 01:12:42799 # gRPC provides some C++ libraries that use std::shared_ptr<>.
Yeunjoo Choi1b644402022-08-25 02:36:10800 '^chromeos/ash/services/libassistant/grpc/',
Vigen Issahhanjanfdf9de52021-12-22 21:13:59801 '^chromecast/cast_core/grpc',
802 '^chromecast/cast_core/runtime/browser',
Yue Shef83d95202022-09-26 20:23:45803 '^ios/chrome/test/earl_grey/chrome_egtest_plugin_client\.(mm|h)',
Wez5f56be52021-05-04 09:30:58804 # Fuchsia provides C++ libraries that use std::shared_ptr<>.
Wez6da2e412022-11-23 11:28:48805 '^base/fuchsia/.*\.(cc|h)',
Wez5f56be52021-05-04 09:30:58806 '.*fuchsia.*test\.(cc|h)',
miktb599ed12023-05-26 07:03:56807 # Clang plugins have different build config.
808 '^tools/clang/plugins/',
Alex Chau9eb03cdd52020-07-13 21:04:57809 _THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell609102be2019-03-27 20:53:21810 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15811 BanRule(
Peter Kasting991618a62019-06-17 22:00:09812 r'/\bstd::weak_ptr\b',
813 (
Peter Kastinge2c5ee82023-02-15 17:23:08814 'std::weak_ptr is banned. Use base::WeakPtr instead.',
Peter Kasting991618a62019-06-17 22:00:09815 ),
816 True,
817 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
818 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15819 BanRule(
Daniel Bratell609102be2019-03-27 20:53:21820 r'/\blong long\b',
821 (
Peter Kastinge2c5ee82023-02-15 17:23:08822 'long long is banned. Use [u]int64_t instead.',
Daniel Bratell609102be2019-03-27 20:53:21823 ),
824 False, # Only a warning since it is already used.
825 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
826 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15827 BanRule(
Daniel Cheng192683f2022-11-01 20:52:44828 r'/\b(absl|std)::any\b',
Daniel Chengc05fcc62022-01-12 16:54:29829 (
Peter Kastinge2c5ee82023-02-15 17:23:08830 '{absl,std}::any are banned due to incompatibility with the component ',
831 'build.',
Daniel Chengc05fcc62022-01-12 16:54:29832 ),
833 True,
834 # Not an error in third party folders, though it probably should be :)
835 [_THIRD_PARTY_EXCEPT_BLINK],
836 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15837 BanRule(
Daniel Bratell609102be2019-03-27 20:53:21838 r'/\bstd::bind\b',
839 (
Peter Kastinge2c5ee82023-02-15 17:23:08840 'std::bind() is banned because of lifetime risks. Use ',
841 'base::Bind{Once,Repeating}() instead.',
Daniel Bratell609102be2019-03-27 20:53:21842 ),
843 True,
844 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
845 ),
Daniel Chenga44a1bcd2022-03-15 20:00:15846 BanRule(
Daniel Cheng192683f2022-11-01 20:52:44847 (
Peter Kastingc7460d982023-03-14 21:01:42848 r'/\bstd::(?:'
849 r'linear_congruential_engine|mersenne_twister_engine|'
850 r'subtract_with_carry_engine|discard_block_engine|'
851 r'independent_bits_engine|shuffle_order_engine|'
852 r'minstd_rand0?|mt19937(_64)?|ranlux(24|48)(_base)?|knuth_b|'
853 r'default_random_engine|'
854 r'random_device|'
855 r'seed_seq'
Daniel Cheng192683f2022-11-01 20:52:44856 r')\b'
857 ),
858 (
859 'STL random number engines and generators are banned. Use the ',
860 'helpers in base/rand_util.h instead, e.g. base::RandBytes() or ',
861 'base::RandomBitGenerator.'
Daniel Cheng57d967762023-10-10 19:03:06862 '',
863 'Please reach out to [email protected] if the base APIs are ',
864 'insufficient for your needs.',
Daniel Cheng192683f2022-11-01 20:52:44865 ),
866 True,
867 [
868 # Not an error in third_party folders.
869 _THIRD_PARTY_EXCEPT_BLINK,
870 # Various tools which build outside of Chrome.
871 r'testing/libfuzzer',
872 r'tools/android/io_benchmark/',
873 # Fuzzers are allowed to use standard library random number generators
874 # since fuzzing speed + reproducibility is important.
875 r'tools/ipc_fuzzer/',
876 r'.+_fuzzer\.cc$',
877 r'.+_fuzzertest\.cc$',
878 # TODO(https://crbug.com/1380528): These are all unsanctioned uses of
879 # the standard library's random number generators, and should be
880 # migrated to the //base equivalent.
881 r'ash/ambient/model/ambient_topic_queue\.cc',
Arthur Sonzogni0bcc0232023-10-03 08:48:32882 r'base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest\.cc',
Daniel Cheng192683f2022-11-01 20:52:44883 r'base/ranges/algorithm_unittest\.cc',
884 r'base/test/launcher/test_launcher\.cc',
885 r'cc/metrics/video_playback_roughness_reporter_unittest\.cc',
886 r'chrome/browser/apps/app_service/metrics/website_metrics\.cc',
887 r'chrome/browser/ash/power/auto_screen_brightness/monotone_cubic_spline_unittest\.cc',
888 r'chrome/browser/ash/printing/zeroconf_printer_detector_unittest\.cc',
889 r'chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl_unittest\.cc',
890 r'chrome/browser/nearby_sharing/contacts/nearby_share_contacts_sorter_unittest\.cc',
891 r'chrome/browser/privacy_budget/mesa_distribution_unittest\.cc',
892 r'chrome/browser/web_applications/test/web_app_test_utils\.cc',
893 r'chrome/browser/web_applications/test/web_app_test_utils\.cc',
894 r'chrome/browser/win/conflicts/module_blocklist_cache_util_unittest\.cc',
Daniel Cheng192683f2022-11-01 20:52:44895 r'chromeos/ash/components/memory/userspace_swap/swap_storage_unittest\.cc',
896 r'chromeos/ash/components/memory/userspace_swap/userspace_swap\.cc',
897 r'components/metrics/metrics_state_manager\.cc',
898 r'components/omnibox/browser/history_quick_provider_performance_unittest\.cc',
899 r'components/zucchini/disassembler_elf_unittest\.cc',
900 r'content/browser/webid/federated_auth_request_impl\.cc',
901 r'content/browser/webid/federated_auth_request_impl\.cc',
902 r'media/cast/test/utility/udp_proxy\.h',
903 r'sql/recover_module/module_unittest\.cc',
Samarc64873a72023-10-10 09:19:12904 r'components/search_engines/template_url_prepopulate_data.cc',
Daniel Cheng57d967762023-10-10 19:03:06905 # Do not add new entries to this list. If you have a use case which is
906 # not satisfied by the current APIs (i.e. you need an explicitly-seeded
907 # sequence, or stability of some sort is required), please contact
908 # [email protected].
Daniel Cheng192683f2022-11-01 20:52:44909 ],
910 ),
911 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:08912 r'/\b(absl,std)::bind_front\b',
Peter Kasting4f35bfc2022-10-18 18:39:12913 (
Peter Kastinge2c5ee82023-02-15 17:23:08914 '{absl,std}::bind_front() are banned. Use base::Bind{Once,Repeating}() '
915 'instead.',
Peter Kasting4f35bfc2022-10-18 18:39:12916 ),
917 True,
918 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
919 ),
920 BanRule(
921 r'/\bABSL_FLAG\b',
922 (
923 'ABSL_FLAG is banned. Use base::CommandLine instead.',
924 ),
925 True,
926 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
927 ),
928 BanRule(
929 r'/\babsl::c_',
930 (
Peter Kastinge2c5ee82023-02-15 17:23:08931 'Abseil container utilities are banned. Use base/ranges/algorithm.h ',
Peter Kasting4f35bfc2022-10-18 18:39:12932 'instead.',
933 ),
934 True,
935 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
936 ),
937 BanRule(
Peter Kasting431239a2023-09-29 03:11:44938 r'/\babsl::FixedArray\b',
939 (
940 'absl::FixedArray is banned. Use base::FixedArray instead.',
941 ),
942 True,
943 [
944 # base::FixedArray provides canonical access.
945 r'^base/types/fixed_array.h',
946 # Not an error in third_party folders.
947 _THIRD_PARTY_EXCEPT_BLINK,
948 ],
949 ),
950 BanRule(
Peter Kasting4f35bfc2022-10-18 18:39:12951 r'/\babsl::FunctionRef\b',
952 (
953 'absl::FunctionRef is banned. Use base::FunctionRef instead.',
954 ),
955 True,
956 [
957 # base::Bind{Once,Repeating} references absl::FunctionRef to disallow
958 # interoperability.
959 r'^base/functional/bind_internal\.h',
960 # base::FunctionRef is implemented on top of absl::FunctionRef.
961 r'^base/functional/function_ref.*\..+',
962 # Not an error in third_party folders.
963 _THIRD_PARTY_EXCEPT_BLINK,
964 ],
965 ),
966 BanRule(
967 r'/\babsl::(Insecure)?BitGen\b',
968 (
Daniel Cheng192683f2022-11-01 20:52:44969 'absl random number generators are banned. Use the helpers in '
970 'base/rand_util.h instead, e.g. base::RandBytes() or ',
971 'base::RandomBitGenerator.'
Peter Kasting4f35bfc2022-10-18 18:39:12972 ),
973 True,
974 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
975 ),
976 BanRule(
danakj44190ab62024-02-08 01:55:49977 r'/(\babsl::Span\b|#include <span>|\bstd::span\b)',
Peter Kasting4f35bfc2022-10-18 18:39:12978 (
danakj44190ab62024-02-08 01:55:49979 'absl::Span and std::span are not allowed ',
Peter Kastinge2c5ee82023-02-15 17:23:08980 '(https://crbug.com/1414652). Use base::span instead.',
Peter Kasting4f35bfc2022-10-18 18:39:12981 ),
982 True,
Victor Vasiliev23b9ea6a2023-01-05 19:42:29983 [
danakj44190ab62024-02-08 01:55:49984 # Included for conversions between base and std.
985 r'base/containers/span.h',
Tom Sepez3b060e32024-01-25 00:14:32986 # Test base::span<> compatibility against std::span<>.
987 r'base/containers/span_unittest.cc',
Victor Vasiliev23b9ea6a2023-01-05 19:42:29988 # Needed to use QUICHE API.
Tsuyoshi Horo758bdb02024-03-14 08:47:24989 r'net/third_party/quiche/overrides/quiche_platform_impl/quiche_stack_trace_impl\.*',
Victor Vasiliev23b9ea6a2023-01-05 19:42:29990 r'services/network/web_transport\.cc',
Brianna Goldstein846d8002023-05-16 19:24:30991 r'chrome/browser/ip_protection/.*',
Victor Vasiliev23b9ea6a2023-01-05 19:42:29992 # Not an error in third_party folders.
danakj590d15232024-02-08 17:17:44993 _THIRD_PARTY_EXCEPT_BLINK,
994 # //base/numerics can't use base or absl.
995 r'base/numerics/.*'
Victor Vasiliev23b9ea6a2023-01-05 19:42:29996 ],
Peter Kasting4f35bfc2022-10-18 18:39:12997 ),
998 BanRule(
999 r'/\babsl::StatusOr\b',
1000 (
1001 'absl::StatusOr is banned. Use base::expected instead.',
1002 ),
1003 True,
Adithya Srinivasanb2041882022-10-21 19:34:201004 [
1005 # Needed to use liburlpattern API.
Tsuyoshi Horoa150b902024-02-05 01:27:151006 r'components/url_pattern/.*',
1007 r'services/network/shared_dictionary/simple_url_pattern_matcher\.cc',
Adithya Srinivasanb2041882022-10-21 19:34:201008 r'third_party/blink/renderer/core/url_pattern/.*',
Louise Brettc6d23872023-04-11 02:48:321009 r'third_party/blink/renderer/modules/manifest/manifest_parser\.cc',
Brianna Goldstein846d8002023-05-16 19:24:301010 # Needed to use QUICHE API.
1011 r'chrome/browser/ip_protection/.*',
Piotr Bialecki7f2549fd2023-10-17 17:49:461012 # Needed to use MediaPipe API.
1013 r'components/media_effects/.*\.cc',
Adithya Srinivasanb2041882022-10-21 19:34:201014 # Not an error in third_party folders.
1015 _THIRD_PARTY_EXCEPT_BLINK
1016 ],
Peter Kasting4f35bfc2022-10-18 18:39:121017 ),
1018 BanRule(
1019 r'/\babsl::StrFormat\b',
1020 (
Peter Kastinge2c5ee82023-02-15 17:23:081021 'absl::StrFormat() is not allowed yet (https://crbug.com/1371963). ',
1022 'Use base::StringPrintf() instead.',
Peter Kasting4f35bfc2022-10-18 18:39:121023 ),
1024 True,
1025 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1026 ),
1027 BanRule(
Peter Kasting4f35bfc2022-10-18 18:39:121028 r'/\babsl::(StrSplit|StrJoin|StrCat|StrAppend|Substitute|StrContains)\b',
1029 (
1030 'Abseil string utilities are banned. Use base/strings instead.',
1031 ),
1032 True,
1033 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1034 ),
1035 BanRule(
1036 r'/\babsl::(Mutex|CondVar|Notification|Barrier|BlockingCounter)\b',
1037 (
1038 'Abseil synchronization primitives are banned. Use',
1039 'base/synchronization instead.',
1040 ),
1041 True,
1042 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1043 ),
1044 BanRule(
1045 r'/\babsl::(Duration|Time|TimeZone|CivilDay)\b',
1046 (
1047 'Abseil\'s time library is banned. Use base/time instead.',
1048 ),
1049 True,
Dustin J. Mitchell626a6d322023-06-26 15:02:481050 [
1051 # Needed to use QUICHE API.
1052 r'chrome/browser/ip_protection/.*',
Victor Vasilieva8638882023-09-25 16:41:041053 r'services/network/web_transport.*',
Dustin J. Mitchell626a6d322023-06-26 15:02:481054 _THIRD_PARTY_EXCEPT_BLINK # Not an error in third_party folders.
1055 ],
Peter Kasting4f35bfc2022-10-18 18:39:121056 ),
1057 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081058 r'/#include <chrono>',
Daniel Bratell609102be2019-03-27 20:53:211059 (
Peter Kastinge2c5ee82023-02-15 17:23:081060 '<chrono> is banned. Use base/time instead.',
Daniel Bratell609102be2019-03-27 20:53:211061 ),
1062 True,
Arthur Sonzogni2ee5e382023-09-11 09:13:031063 [
1064 # Not an error in third_party folders:
1065 _THIRD_PARTY_EXCEPT_BLINK,
1066 # PartitionAlloc's starscan, doesn't depend on base/. It can't use
1067 # base::ConditionalVariable::TimedWait(..).
Arthur Sonzogni0bcc0232023-10-03 08:48:321068 "base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.cc",
Arthur Sonzogni2ee5e382023-09-11 09:13:031069 ]
Daniel Bratell609102be2019-03-27 20:53:211070 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151071 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081072 r'/#include <exception>',
Daniel Bratell609102be2019-03-27 20:53:211073 (
1074 'Exceptions are banned and disabled in Chromium.',
1075 ),
1076 True,
1077 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1078 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151079 BanRule(
Daniel Bratell609102be2019-03-27 20:53:211080 r'/\bstd::function\b',
1081 (
Peter Kastinge2c5ee82023-02-15 17:23:081082 'std::function is banned. Use base::{Once,Repeating}Callback instead.',
Daniel Bratell609102be2019-03-27 20:53:211083 ),
Daniel Chenge5583e3c2022-09-22 00:19:411084 True,
Daniel Chengcd23b8b2022-09-16 17:16:241085 [
1086 # Has tests that template trait helpers don't unintentionally match
1087 # std::function.
Daniel Chenge5583e3c2022-09-22 00:19:411088 r'base/functional/callback_helpers_unittest\.cc',
1089 # Required to implement interfaces from the third-party perfetto
1090 # library.
1091 r'base/tracing/perfetto_task_runner\.cc',
1092 r'base/tracing/perfetto_task_runner\.h',
1093 # Needed for interop with the third-party nearby library type
1094 # location::nearby::connections::ResultCallback.
1095 'chrome/services/sharing/nearby/nearby_connections_conversions\.cc'
1096 # Needed for interop with the internal libassistant library.
1097 'chromeos/ash/services/libassistant/callback_utils\.h',
1098 # Needed for interop with Fuchsia fidl APIs.
1099 'fuchsia_web/webengine/browser/context_impl_browsertest\.cc',
1100 'fuchsia_web/webengine/browser/cookie_manager_impl_unittest\.cc',
1101 'fuchsia_web/webengine/browser/media_player_impl_unittest\.cc',
Ken Rockot2af0d1742023-11-22 17:03:471102 # Required to interop with interfaces from the third-party ChromeML
1103 # library API.
1104 'services/on_device_model/ml/chrome_ml_api\.h',
1105 'services/on_device_model/ml/on_device_model_executor\.cc',
1106 'services/on_device_model/ml/on_device_model_executor\.h',
Daniel Chenge5583e3c2022-09-22 00:19:411107 # Required to interop with interfaces from the third-party perfetto
1108 # library.
1109 'services/tracing/public/cpp/perfetto/custom_event_recorder\.cc',
1110 'services/tracing/public/cpp/perfetto/perfetto_traced_process\.cc',
1111 'services/tracing/public/cpp/perfetto/perfetto_traced_process\.h',
1112 'services/tracing/public/cpp/perfetto/perfetto_tracing_backend\.cc',
1113 'services/tracing/public/cpp/perfetto/producer_client\.cc',
1114 'services/tracing/public/cpp/perfetto/producer_client\.h',
1115 'services/tracing/public/cpp/perfetto/producer_test_utils\.cc',
1116 'services/tracing/public/cpp/perfetto/producer_test_utils\.h',
1117 # Required for interop with the third-party webrtc library.
1118 'third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl\.cc',
1119 'third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl\.h',
Daniel Chenge5583e3c2022-09-22 00:19:411120 # TODO(https://crbug.com/1364577): Various uses that should be
1121 # migrated to something else.
1122 # Should use base::OnceCallback or base::RepeatingCallback.
1123 'base/allocator/dispatcher/initializer_unittest\.cc',
1124 'chrome/browser/ash/accessibility/speech_monitor\.cc',
1125 'chrome/browser/ash/accessibility/speech_monitor\.h',
1126 'chrome/browser/ash/login/ash_hud_login_browsertest\.cc',
1127 'chromecast/base/observer_unittest\.cc',
1128 'chromecast/browser/cast_web_view\.h',
1129 'chromecast/public/cast_media_shlib\.h',
1130 'device/bluetooth/floss/exported_callback_manager\.h',
1131 'device/bluetooth/floss/floss_dbus_client\.h',
1132 'device/fido/cable/v2_handshake_unittest\.cc',
1133 'device/fido/pin\.cc',
1134 'services/tracing/perfetto/test_utils\.h',
1135 # Should use base::FunctionRef.
1136 'chrome/browser/media/webrtc/test_stats_dictionary\.cc',
1137 'chrome/browser/media/webrtc/test_stats_dictionary\.h',
1138 'chromeos/ash/services/libassistant/device_settings_controller\.cc',
1139 'components/browser_ui/client_certificate/android/ssl_client_certificate_request\.cc',
1140 'components/gwp_asan/client/sampling_malloc_shims_unittest\.cc',
1141 'content/browser/font_unique_name_lookup/font_unique_name_lookup_unittest\.cc',
1142 # Does not need std::function at all.
1143 'components/omnibox/browser/autocomplete_result\.cc',
1144 'device/fido/win/webauthn_api\.cc',
1145 'media/audio/alsa/alsa_util\.cc',
1146 'media/remoting/stream_provider\.h',
1147 'sql/vfs_wrapper\.cc',
1148 # TODO(https://crbug.com/1364585): Remove usage and exception list
1149 # entries.
1150 'extensions/renderer/api/automation/automation_internal_custom_bindings\.cc',
1151 'extensions/renderer/api/automation/automation_internal_custom_bindings\.h',
1152 # TODO(https://crbug.com/1364579): Remove usage and exception list
1153 # entry.
1154 'ui/views/controls/focus_ring\.h',
1155
1156 # Various pre-existing uses in //tools that is low-priority to fix.
1157 'tools/binary_size/libsupersize/viewer/caspian/diff\.cc',
1158 'tools/binary_size/libsupersize/viewer/caspian/model\.cc',
1159 'tools/binary_size/libsupersize/viewer/caspian/model\.h',
1160 'tools/binary_size/libsupersize/viewer/caspian/tree_builder\.h',
1161 'tools/clang/base_bind_rewriters/BaseBindRewriters\.cpp',
1162
Daniel Chengcd23b8b2022-09-16 17:16:241163 # Not an error in third_party folders.
1164 _THIRD_PARTY_EXCEPT_BLINK
1165 ],
Daniel Bratell609102be2019-03-27 20:53:211166 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151167 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081168 r'/#include <X11/',
Tom Andersona95e12042020-09-09 23:08:001169 (
1170 'Do not use Xlib. Use xproto (from //ui/gfx/x:xproto) instead.',
1171 ),
1172 True,
1173 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1174 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151175 BanRule(
Daniel Bratell609102be2019-03-27 20:53:211176 r'/\bstd::ratio\b',
1177 (
1178 'std::ratio is banned by the Google Style Guide.',
1179 ),
1180 True,
1181 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:451182 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151183 BanRule(
Peter Kasting6d77e9d2023-02-09 21:58:181184 r'/\bstd::aligned_alloc\b',
1185 (
Peter Kastinge2c5ee82023-02-15 17:23:081186 'std::aligned_alloc() is not yet allowed (crbug.com/1412818). Use ',
1187 'base::AlignedAlloc() instead.',
Peter Kasting6d77e9d2023-02-09 21:58:181188 ),
1189 True,
1190 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1191 ),
1192 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081193 r'/#include <(barrier|latch|semaphore|stop_token)>',
Peter Kasting6d77e9d2023-02-09 21:58:181194 (
Peter Kastinge2c5ee82023-02-15 17:23:081195 'The thread support library is banned. Use base/synchronization '
1196 'instead.',
Peter Kasting6d77e9d2023-02-09 21:58:181197 ),
1198 True,
1199 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1200 ),
1201 BanRule(
Helmut Januschka7cc8a84f2024-02-07 22:50:411202 r'/\bstd::execution::(par|seq)\b',
1203 (
1204 'std::execution::(par|seq) is banned; they do not fit into '
1205 ' Chrome\'s threading model, and libc++ doesn\'t have full '
1206 'support.'
1207 ),
1208 True,
1209 [_THIRD_PARTY_EXCEPT_BLINK],
1210 ),
1211 BanRule(
Avi Drissman70cb7f72023-12-12 17:44:371212 r'/\bstd::bit_cast\b',
1213 (
1214 'std::bit_cast is banned; use base::bit_cast instead for values and '
1215 'standard C++ casting when pointers are involved.',
1216 ),
1217 True,
danakj590d15232024-02-08 17:17:441218 [
1219 # Don't warn in third_party folders.
1220 _THIRD_PARTY_EXCEPT_BLINK,
1221 # //base/numerics can't use base or absl.
1222 r'base/numerics/.*'
1223 ],
Avi Drissman70cb7f72023-12-12 17:44:371224 ),
1225 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081226 r'/\bstd::(c8rtomb|mbrtoc8)\b',
Peter Kasting6d77e9d2023-02-09 21:58:181227 (
Peter Kastinge2c5ee82023-02-15 17:23:081228 'std::c8rtomb() and std::mbrtoc8() are banned.',
Peter Kasting6d77e9d2023-02-09 21:58:181229 ),
1230 True,
1231 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1232 ),
1233 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081234 r'/\bchar8_t|std::u8string\b',
Peter Kasting6d77e9d2023-02-09 21:58:181235 (
Peter Kastinge2c5ee82023-02-15 17:23:081236 'char8_t and std::u8string are not yet allowed. Can you use [unsigned]',
1237 ' char and std::string instead?',
1238 ),
1239 True,
Daniel Cheng893c563f2023-04-21 09:54:521240 [
1241 # The demangler does not use this type but needs to know about it.
1242 'base/third_party/symbolize/demangle\.cc',
1243 # Don't warn in third_party folders.
1244 _THIRD_PARTY_EXCEPT_BLINK
1245 ],
Peter Kastinge2c5ee82023-02-15 17:23:081246 ),
1247 BanRule(
1248 r'/(\b(co_await|co_return|co_yield)\b|#include <coroutine>)',
1249 (
1250 'Coroutines are not yet allowed (https://crbug.com/1403840).',
1251 ),
1252 True,
1253 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1254 ),
1255 BanRule(
Peter Kastingcc152522023-03-22 20:17:371256 r'/^\s*(export\s|import\s+["<:\w]|module(;|\s+[:\w]))',
Peter Kasting69357dc2023-03-14 01:34:291257 (
1258 'Modules are disallowed for now due to lack of toolchain support.',
1259 ),
1260 True,
1261 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1262 ),
1263 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081264 r'/\[\[(un)?likely\]\]',
1265 (
1266 '[[likely]] and [[unlikely]] are not yet allowed ',
1267 '(https://crbug.com/1414620). Use [UN]LIKELY instead.',
1268 ),
1269 True,
1270 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1271 ),
1272 BanRule(
Peter Kasting8bc046d22023-11-14 00:38:031273 r'/\[\[(\w*::)?no_unique_address\]\]',
1274 (
1275 '[[no_unique_address]] does not work as expected on Windows ',
1276 '(https://crbug.com/1414621). Use NO_UNIQUE_ADDRESS instead.',
1277 ),
1278 True,
1279 [
Daniel Chenga04e0d22024-01-16 18:27:251280 # NO_UNIQUE_ADDRESS / PA_NO_UNIQUE_ADDRESS provide canonical access.
1281 r'^base/compiler_specific\.h',
1282 r'^base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/compiler_specific\.h',
Peter Kasting8bc046d22023-11-14 00:38:031283 # Not an error in third_party folders.
1284 _THIRD_PARTY_EXCEPT_BLINK,
1285 ],
1286 ),
1287 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081288 r'/#include <format>',
1289 (
1290 '<format> is not yet allowed. Use base::StringPrintf() instead.',
1291 ),
1292 True,
1293 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1294 ),
1295 BanRule(
1296 r'/#include <ranges>',
1297 (
1298 '<ranges> is not yet allowed. Use base/ranges/algorithm.h instead.',
1299 ),
1300 True,
1301 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1302 ),
1303 BanRule(
1304 r'/#include <source_location>',
1305 (
1306 '<source_location> is not yet allowed. Use base/location.h instead.',
1307 ),
1308 True,
1309 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1310 ),
1311 BanRule(
Nick Diego Yamanee522ae82024-02-27 04:23:221312 r'/\bstd::to_address\b',
1313 (
1314 'std::to_address is banned because it is not guaranteed to be',
1315 'SFINAE-compatible. Use base::to_address instead.',
1316 ),
1317 True,
1318 [
1319 # Needed in base::to_address implementation.
1320 r'base/types/to_address.h',
1321 _THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1322 ),
1323 BanRule(
Peter Kastinge2c5ee82023-02-15 17:23:081324 r'/#include <syncstream>',
1325 (
1326 '<syncstream> is banned.',
Peter Kasting6d77e9d2023-02-09 21:58:181327 ),
1328 True,
1329 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
1330 ),
1331 BanRule(
Michael Giuffrida7f93d6922019-04-19 14:39:581332 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:191333 (
1334 'RunMessageLoop is deprecated, use RunLoop instead.',
1335 ),
1336 False,
1337 (),
1338 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151339 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441340 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:191341 (
1342 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
1343 "if you're convinced you need this.",
1344 ),
1345 False,
1346 (),
1347 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151348 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441349 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:191350 (
1351 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:041352 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:191353 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
1354 'async events instead of flushing threads.',
1355 ),
1356 False,
1357 (),
1358 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151359 BanRule(
Gabriel Charette147335ea2018-03-22 15:59:191360 r'MessageLoopRunner',
1361 (
1362 'MessageLoopRunner is deprecated, use RunLoop instead.',
1363 ),
1364 False,
1365 (),
1366 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151367 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441368 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:191369 (
1370 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
1371 "gab@ if you found a use case where this is the only solution.",
1372 ),
1373 False,
1374 (),
1375 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151376 BanRule(
Victor Costane48a2e82019-03-15 22:02:341377 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161378 (
Victor Costane48a2e82019-03-15 22:02:341379 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161380 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1381 ),
1382 True,
1383 (
1384 r'^sql/initialization\.(cc|h)$',
1385 r'^third_party/sqlite/.*\.(c|cc|h)$',
1386 ),
1387 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151388 BanRule(
Austin Sullivand661ab52022-11-16 08:55:151389 'CREATE VIEW',
1390 (
1391 'SQL views are disabled in Chromium feature code',
1392 'https://chromium.googlesource.com/chromium/src/+/HEAD/sql#no-views',
1393 ),
1394 True,
1395 (
1396 _THIRD_PARTY_EXCEPT_BLINK,
1397 # sql/ itself uses views when using memory-mapped IO.
1398 r'^sql/.*',
1399 # Various performance tools that do not build as part of Chrome.
1400 r'^infra/.*',
1401 r'^tools/perf.*',
1402 r'.*perfetto.*',
1403 ),
1404 ),
1405 BanRule(
1406 'CREATE VIRTUAL TABLE',
1407 (
1408 'SQL virtual tables are disabled in Chromium feature code',
1409 'https://chromium.googlesource.com/chromium/src/+/HEAD/sql#no-virtual-tables',
1410 ),
1411 True,
1412 (
1413 _THIRD_PARTY_EXCEPT_BLINK,
1414 # sql/ itself uses virtual tables in the recovery module and tests.
1415 r'^sql/.*',
1416 # TODO(https://crbug.com/695592): Remove once WebSQL is deprecated.
1417 r'third_party/blink/web_tests/storage/websql/.*'
1418 # Various performance tools that do not build as part of Chrome.
1419 r'^tools/perf.*',
1420 r'.*perfetto.*',
1421 ),
1422 ),
1423 BanRule(
Dave Tapuska98199b612019-07-10 13:30:441424 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471425 (
1426 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1427 'base::RandomShuffle instead.'
1428 ),
1429 True,
1430 (),
1431 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151432 BanRule(
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241433 'ios/web/public/test/http_server',
1434 (
1435 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1436 ),
1437 False,
1438 (),
1439 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151440 BanRule(
Robert Liao764c9492019-01-24 18:46:281441 'GetAddressOf',
1442 (
1443 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Xiaohan Wangfb31b4cd2020-07-08 01:18:531444 'implicated in a few leaks. ReleaseAndGetAddressOf() is safe but ',
Joshua Berenhaus8b972ec2020-09-11 20:00:111445 'operator& is generally recommended. So always use operator& instead. ',
Xiaohan Wangfb31b4cd2020-07-08 01:18:531446 'See http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:281447 ),
1448 True,
1449 (),
1450 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151451 BanRule(
Ben Lewisa9514602019-04-29 17:53:051452 'SHFileOperation',
1453 (
1454 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1455 'complex functions to achieve the same goals. Use IFileOperation for ',
1456 'any esoteric actions instead.'
1457 ),
1458 True,
1459 (),
1460 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151461 BanRule(
Cliff Smolinsky81951642019-04-30 21:39:511462 'StringFromGUID2',
1463 (
1464 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
Jan Wilken Dörrieec815922020-07-22 07:46:241465 'Use base::win::WStringFromGUID instead.'
Cliff Smolinsky81951642019-04-30 21:39:511466 ),
1467 True,
1468 (
Daniel Chenga44a1bcd2022-03-15 20:00:151469 r'/base/win/win_util_unittest.cc',
Cliff Smolinsky81951642019-04-30 21:39:511470 ),
1471 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151472 BanRule(
Cliff Smolinsky81951642019-04-30 21:39:511473 'StringFromCLSID',
1474 (
1475 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
Jan Wilken Dörrieec815922020-07-22 07:46:241476 'Use base::win::WStringFromGUID instead.'
Cliff Smolinsky81951642019-04-30 21:39:511477 ),
1478 True,
1479 (
Daniel Chenga44a1bcd2022-03-15 20:00:151480 r'/base/win/win_util_unittest.cc',
Cliff Smolinsky81951642019-04-30 21:39:511481 ),
1482 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151483 BanRule(
Avi Drissman7382afa02019-04-29 23:27:131484 'kCFAllocatorNull',
1485 (
1486 'The use of kCFAllocatorNull with the NoCopy creation of ',
1487 'CoreFoundation types is prohibited.',
1488 ),
1489 True,
1490 (),
1491 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151492 BanRule(
Oksana Zhuravlovafd247772019-05-16 16:57:291493 'mojo::ConvertTo',
1494 (
1495 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1496 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1497 'StringTraits if you would like to convert between custom types and',
1498 'the wire format of mojom types.'
1499 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221500 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291501 (
David Dorwin13dc48b2022-06-03 21:18:421502 r'^fuchsia_web/webengine/browser/url_request_rewrite_rules_manager\.cc$',
1503 r'^fuchsia_web/webengine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291504 r'^third_party/blink/.*\.(cc|h)$',
1505 r'^content/renderer/.*\.(cc|h)$',
1506 ),
1507 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151508 BanRule(
Oksana Zhuravlovac8222d22019-12-19 19:21:161509 'GetInterfaceProvider',
1510 (
1511 'InterfaceProvider is deprecated.',
1512 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1513 'or Platform::GetBrowserInterfaceBroker.'
1514 ),
1515 False,
1516 (),
1517 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151518 BanRule(
Robert Liao1d78df52019-11-11 20:02:011519 'CComPtr',
1520 (
1521 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1522 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1523 'details.'
1524 ),
1525 False,
1526 (),
1527 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151528 BanRule(
Xiaohan Wang72bd2ba2020-02-18 21:38:201529 r'/\b(IFACE|STD)METHOD_?\(',
1530 (
1531 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1532 'Instead, always use IFACEMETHODIMP in the declaration.'
1533 ),
1534 False,
1535 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1536 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151537 BanRule(
Allen Bauer53b43fb12020-03-12 17:21:471538 'set_owned_by_client',
1539 (
1540 'set_owned_by_client is deprecated.',
1541 'views::View already owns the child views by default. This introduces ',
1542 'a competing ownership model which makes the code difficult to reason ',
1543 'about. See http://crbug.com/1044687 for more details.'
1544 ),
1545 False,
1546 (),
1547 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151548 BanRule(
Peter Boström7ff41522021-07-29 03:43:271549 'RemoveAllChildViewsWithoutDeleting',
1550 (
1551 'RemoveAllChildViewsWithoutDeleting is deprecated.',
1552 'This method is deemed dangerous as, unless raw pointers are re-added,',
1553 'calls to this method introduce memory leaks.'
1554 ),
1555 False,
1556 (),
1557 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151558 BanRule(
Eric Secklerbe6f48d2020-05-06 18:09:121559 r'/\bTRACE_EVENT_ASYNC_',
1560 (
1561 'Please use TRACE_EVENT_NESTABLE_ASYNC_.. macros instead',
1562 'of TRACE_EVENT_ASYNC_.. (crbug.com/1038710).',
1563 ),
1564 False,
1565 (
1566 r'^base/trace_event/.*',
1567 r'^base/tracing/.*',
1568 ),
1569 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151570 BanRule(
Aditya Kushwah5a286b72022-02-10 04:54:431571 r'/\bbase::debug::DumpWithoutCrashingUnthrottled[(][)]',
1572 (
1573 'base::debug::DumpWithoutCrashingUnthrottled() does not throttle',
1574 'dumps and may spam crash reports. Consider if the throttled',
1575 'variants suffice instead.',
1576 ),
1577 False,
1578 (),
1579 ),
Daniel Chenga44a1bcd2022-03-15 20:00:151580 BanRule(
Robert Liao22f66a52021-04-10 00:57:521581 'RoInitialize',
1582 (
Robert Liao48018922021-04-16 23:03:021583 'Improper use of [base::win]::RoInitialize() has been implicated in a ',
Robert Liao22f66a52021-04-10 00:57:521584 'few COM initialization leaks. Use base::win::ScopedWinrtInitializer ',
1585 'instead. See http://crbug.com/1197722 for more information.'
1586 ),
1587 True,
Robert Liao48018922021-04-16 23:03:021588 (
Bruce Dawson40fece62022-09-16 19:58:311589 r'^base/win/scoped_winrt_initializer\.cc$',
Danil Chapovalov07694382023-05-24 17:55:211590 r'^third_party/abseil-cpp/absl/.*',
Robert Liao48018922021-04-16 23:03:021591 ),
Robert Liao22f66a52021-04-10 00:57:521592 ),
Patrick Monettec343bb982022-06-01 17:18:451593 BanRule(
1594 r'base::Watchdog',
1595 (
1596 'base::Watchdog is deprecated because it creates its own thread.',
1597 'Instead, manually start a timer on a SequencedTaskRunner.',
1598 ),
1599 False,
1600 (),
1601 ),
Andrew Rayskiy04a51ce2022-06-07 11:47:091602 BanRule(
1603 'base::Passed',
1604 (
1605 'Do not use base::Passed. It is a legacy helper for capturing ',
1606 'move-only types with base::BindRepeating, but invoking the ',
1607 'resulting RepeatingCallback moves the captured value out of ',
1608 'the callback storage, and subsequent invocations may pass the ',
1609 'value in a valid but undefined state. Prefer base::BindOnce().',
1610 'See http://crbug.com/1326449 for context.'
1611 ),
1612 False,
Daniel Cheng91f6fbaf2022-09-16 12:07:481613 (
1614 # False positive, but it is also fine to let bind internals reference
1615 # base::Passed.
Daniel Chengcd23b8b2022-09-16 17:16:241616 r'^base[\\/]functional[\\/]bind\.h',
Daniel Cheng91f6fbaf2022-09-16 12:07:481617 r'^base[\\/]functional[\\/]bind_internal\.h',
1618 ),
Andrew Rayskiy04a51ce2022-06-07 11:47:091619 ),
Daniel Cheng2248b332022-07-27 06:16:591620 BanRule(
Daniel Chengba3bc2e2022-10-03 02:45:431621 r'base::Feature k',
1622 (
1623 'Please use BASE_DECLARE_FEATURE() or BASE_FEATURE() instead of ',
1624 'directly declaring/defining features.'
1625 ),
1626 True,
1627 [
Daniel Chengb000a8c2023-12-08 04:37:281628 # Implements BASE_DECLARE_FEATURE().
1629 r'^base/feature_list\.h',
Daniel Chengba3bc2e2022-10-03 02:45:431630 ],
1631 ),
Robert Ogden92101dcb2022-10-19 23:49:361632 BanRule(
Arthur Sonzogni1da65fa2023-03-27 16:01:521633 r'/\bchartorune\b',
Robert Ogden92101dcb2022-10-19 23:49:361634 (
1635 'chartorune is not memory-safe, unless you can guarantee the input ',
1636 'string is always null-terminated. Otherwise, please use charntorune ',
1637 'from libphonenumber instead.'
1638 ),
1639 True,
1640 [
1641 _THIRD_PARTY_EXCEPT_BLINK,
1642 # Exceptions to this rule should have a fuzzer.
1643 ],
1644 ),
Arthur Sonzogni1da65fa2023-03-27 16:01:521645 BanRule(
1646 r'/\b#include "base/atomicops\.h"\b',
1647 (
1648 'Do not use base::subtle atomics, but std::atomic, which are simpler '
1649 'to use, have better understood, clearer and richer semantics, and are '
1650 'harder to mis-use. See details in base/atomicops.h.',
1651 ),
1652 False,
1653 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Benoit Lize79cf0592023-01-27 10:01:571654 ),
Arthur Sonzogni60348572e2023-04-07 10:22:521655 BanRule(
1656 r'CrossThreadPersistent<',
1657 (
1658 'Do not use blink::CrossThreadPersistent, but '
1659 'blink::CrossThreadHandle. It is harder to mis-use.',
1660 'More info: '
1661 'https://docs.google.com/document/d/1GIT0ysdQ84sGhIo1r9EscF_fFt93lmNVM_q4vvHj2FQ/edit#heading=h.3e4d6y61tgs',
1662 'Please contact platform-architecture-dev@ before adding new instances.'
1663 ),
1664 False,
1665 []
1666 ),
1667 BanRule(
1668 r'CrossThreadWeakPersistent<',
1669 (
1670 'Do not use blink::CrossThreadWeakPersistent, but '
1671 'blink::CrossThreadWeakHandle. It is harder to mis-use.',
1672 'More info: '
1673 'https://docs.google.com/document/d/1GIT0ysdQ84sGhIo1r9EscF_fFt93lmNVM_q4vvHj2FQ/edit#heading=h.3e4d6y61tgs',
1674 'Please contact platform-architecture-dev@ before adding new instances.'
1675 ),
1676 False,
1677 []
1678 ),
Avi Drissman491617c2023-04-13 17:33:151679 BanRule(
1680 r'objc/objc.h',
1681 (
1682 'Do not include <objc/objc.h>. It defines away ARC lifetime '
1683 'annotations, and is thus dangerous.',
1684 'Please use the pimpl pattern; search for `ObjCStorage` for examples.',
1685 'For further reading on how to safely mix C++ and Obj-C, see',
1686 'https://chromium.googlesource.com/chromium/src/+/main/docs/mac/mixing_cpp_and_objc.md'
1687 ),
1688 True,
1689 []
1690 ),
Grace Park8d59b54b2023-04-26 17:53:351691 BanRule(
1692 r'/#include <filesystem>',
1693 (
1694 'libc++ <filesystem> is banned per the Google C++ styleguide.',
1695 ),
1696 True,
1697 # This fuzzing framework is a standalone open source project and
1698 # cannot rely on Chromium base.
1699 (r'third_party/centipede'),
1700 ),
Daniel Cheng72153e02023-05-18 21:18:141701 BanRule(
1702 r'TopDocument()',
1703 (
1704 'TopDocument() does not work correctly with out-of-process iframes. '
1705 'Please do not introduce new uses.',
1706 ),
1707 True,
1708 (
1709 # TODO(crbug.com/617677): Remove all remaining uses.
1710 r'^third_party/blink/renderer/core/dom/document\.cc',
1711 r'^third_party/blink/renderer/core/dom/document\.h',
1712 r'^third_party/blink/renderer/core/dom/element\.cc',
1713 r'^third_party/blink/renderer/core/exported/web_disallow_transition_scope_test\.cc',
1714 r'^third_party/blink/renderer/core/exported/web_document_test\.cc',
Daniel Cheng72153e02023-05-18 21:18:141715 r'^third_party/blink/renderer/core/html/html_anchor_element\.cc',
1716 r'^third_party/blink/renderer/core/html/html_dialog_element\.cc',
1717 r'^third_party/blink/renderer/core/html/html_element\.cc',
1718 r'^third_party/blink/renderer/core/html/html_frame_owner_element\.cc',
1719 r'^third_party/blink/renderer/core/html/media/video_wake_lock\.cc',
1720 r'^third_party/blink/renderer/core/loader/anchor_element_interaction_tracker\.cc',
1721 r'^third_party/blink/renderer/core/page/scrolling/root_scroller_controller\.cc',
1722 r'^third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller\.cc',
1723 r'^third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller\.h',
1724 r'^third_party/blink/renderer/core/script/classic_pending_script\.cc',
1725 r'^third_party/blink/renderer/core/script/script_loader\.cc',
1726 ),
1727 ),
Arthur Sonzognif0eea302023-08-18 19:20:311728 BanRule(
1729 pattern = r'base::raw_ptr<',
1730 explanation = (
1731 'Do not use base::raw_ptr, use raw_ptr.',
1732 ),
1733 treat_as_error = True,
1734 excluded_paths = (
1735 '^base/',
1736 '^tools/',
1737 ),
1738 ),
1739 BanRule(
1740 pattern = r'base:raw_ref<',
1741 explanation = (
1742 'Do not use base::raw_ref, use raw_ref.',
1743 ),
1744 treat_as_error = True,
1745 excluded_paths = (
1746 '^base/',
1747 '^tools/',
1748 ),
1749 ),
Anton Maliev66751812023-08-24 16:28:131750 BanRule(
Tom Sepez41eb158d2023-09-12 16:16:221751 pattern = r'/raw_ptr<[^;}]*\w{};',
1752 explanation = (
1753 'Do not use {} for raw_ptr initialization, use = nullptr instead.',
1754 ),
1755 treat_as_error = True,
1756 excluded_paths = (
1757 '^base/',
1758 '^tools/',
1759 ),
1760 ),
1761 BanRule(
Arthur Sonzogni48c6aea22023-09-04 22:25:201762 pattern = r'/#include "base/allocator/.*/raw_'
1763 r'(ptr|ptr_cast|ptr_exclusion|ref).h"',
1764 explanation = (
1765 'Please include the corresponding facade headers:',
1766 '- #include "base/memory/raw_ptr.h"',
1767 '- #include "base/memory/raw_ptr_cast.h"',
1768 '- #include "base/memory/raw_ptr_exclusion.h"',
1769 '- #include "base/memory/raw_ref.h"',
1770 ),
1771 treat_as_error = True,
1772 excluded_paths = (
1773 '^base/',
1774 '^tools/',
1775 ),
1776 ),
1777 BanRule(
Anton Maliev66751812023-08-24 16:28:131778 pattern = r'ContentSettingsType::COOKIES',
1779 explanation = (
1780 'Do not use ContentSettingsType::COOKIES to check whether cookies are '
1781 'supported in the provided context. Instead rely on the '
1782 'content_settings::CookieSettings API. If you are using '
1783 'ContentSettingsType::COOKIES to check the user preference setting '
1784 'specifically, disregard this warning.',
1785 ),
1786 treat_as_error = False,
1787 excluded_paths = (
1788 '^chrome/browser/ui/content_settings/',
1789 '^components/content_settings/',
Christian Dullweber61416642023-10-05 11:46:431790 '^services/network/cookie_settings.cc',
1791 '.*test.cc',
Anton Maliev66751812023-08-24 16:28:131792 ),
1793 ),
Tom Andersoncd522072023-10-03 00:52:351794 BanRule(
Tom Anderson11e4a732024-02-12 23:57:221795 pattern = r'/\bg_signal_connect',
Tom Andersoncd522072023-10-03 00:52:351796 explanation = (
1797 'Use ScopedGSignal instead of g_signal_connect*()',
1798 ),
1799 treat_as_error = True,
1800 excluded_paths = (
1801 '^ui/base/glib/scoped_gsignal.h',
1802 ),
1803 ),
Christian Flach8da3bf82023-10-12 09:42:531804 BanRule(
1805 pattern = r'features::kIsolatedWebApps',
1806 explanation = (
1807 'Do not use `features::kIsolatedWebApps` directly to guard Isolated ',
1808 'Web App code. ',
1809 'Use `content::IsolatedWebAppsPolicy::AreIsolatedWebAppsEnabled()` in ',
1810 'the browser process or check the `kEnableIsolatedWebAppsInRenderer` ',
1811 'command line flag in the renderer process.',
1812 ),
1813 treat_as_error = True,
1814 excluded_paths = _TEST_CODE_EXCLUDED_PATHS + (
1815 '^chrome/browser/about_flags.cc',
Andrew Rayskiy93a6b0b32024-03-08 00:04:331816 '^chrome/browser/web_applications/isolated_web_apps/chrome_content_browser_client_isolated_web_apps_part.cc',
Christian Flach8da3bf82023-10-12 09:42:531817 '^chrome/browser/ui/startup/bad_flags_prompt.cc',
1818 '^content/shell/browser/shell_content_browser_client.cc'
1819 )
1820 ),
Arthur Sonzogni5cbd3e32024-02-08 17:51:321821 BanRule(
Andrew Rayskiycdd45e732024-03-20 14:32:391822 pattern = r'features::kIsolatedWebAppDevMode',
1823 explanation = (
1824 'Do not use `features::kIsolatedWebAppDevMode` directly to guard code ',
1825 'related to Isolated Web App Developer Mode. ',
1826 'Use `web_app::IsIwaDevModeEnabled()` instead.',
1827 ),
1828 treat_as_error = True,
1829 excluded_paths = _TEST_CODE_EXCLUDED_PATHS + (
1830 '^chrome/browser/about_flags.cc',
1831 '^chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.cc',
1832 '^chrome/browser/ui/startup/bad_flags_prompt.cc',
1833 )
1834 ),
1835 BanRule(
1836 pattern = r'features::kIsolatedWebAppUnmanagedInstall',
1837 explanation = (
1838 'Do not use `features::kIsolatedWebAppUnmanagedInstall` directly to ',
1839 'guard code related to unmanaged install flow for Isolated Web Apps. ',
1840 'Use `web_app::IsIwaUnmanagedInstallEnabled()` instead.',
1841 ),
1842 treat_as_error = True,
1843 excluded_paths = _TEST_CODE_EXCLUDED_PATHS + (
1844 '^chrome/browser/about_flags.cc',
1845 '^chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.cc',
1846 )
1847 ),
1848 BanRule(
Arthur Sonzognia9dd4a7b2024-02-13 08:07:271849 pattern = r'/\babsl::(optional|nullopt|make_optional|in_place|in_place_t)\b',
Arthur Sonzogni5cbd3e32024-02-08 17:51:321850 explanation = (
Helmut Januschkab3f71ab52024-03-12 02:48:051851 'Don\'t use `absl::optional`. Use `std::optional`.',
Arthur Sonzogni5cbd3e32024-02-08 17:51:321852 ),
1853 # TODO(b/40288126): Enforce after completing the rewrite.
1854 treat_as_error = False,
1855 excluded_paths = [
1856 _THIRD_PARTY_EXCEPT_BLINK,
1857 ]
1858 ),
Helmut Januschkab3f71ab52024-03-12 02:48:051859 BanRule(
1860 pattern = r'(base::)?\bStringPiece\b',
1861 explanation = (
1862 'Don\'t use `base::StringPiece`. Use `std::string_view`.',
1863 ),
1864 treat_as_error = False,
1865 ),
1866 BanRule(
1867 pattern = r'(base::)?\bStringPiece16\b',
1868 explanation = (
1869 'Don\'t use `base::StringPiece16`. Use `std::u16string_view`.',
1870 ),
1871 treat_as_error = False,
1872 ),
[email protected]127f18ec2012-06-16 05:05:591873)
1874
Daniel Cheng92c15e32022-03-16 17:48:221875_BANNED_MOJOM_PATTERNS : Sequence[BanRule] = (
1876 BanRule(
1877 'handle<shared_buffer>',
1878 (
1879 'Please use one of the more specific shared memory types instead:',
1880 ' mojo_base.mojom.ReadOnlySharedMemoryRegion',
1881 ' mojo_base.mojom.WritableSharedMemoryRegion',
1882 ' mojo_base.mojom.UnsafeSharedMemoryRegion',
1883 ),
1884 True,
1885 ),
1886)
1887
mlamouria82272622014-09-16 18:45:041888_IPC_ENUM_TRAITS_DEPRECATED = (
1889 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501890 'See http://www.chromium.org/Home/chromium-security/education/'
1891 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041892
Stephen Martinis97a394142018-06-07 23:06:051893_LONG_PATH_ERROR = (
1894 'Some files included in this CL have file names that are too long (> 200'
1895 ' characters). If committed, these files will cause issues on Windows. See'
1896 ' https://crbug.com/612667 for more details.'
1897)
1898
Shenghua Zhangbfaa38b82017-11-16 21:58:021899_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Bruce Dawson40fece62022-09-16 19:58:311900 r".*/AppHooksImpl\.java",
1901 r".*/BuildHooksAndroidImpl\.java",
1902 r".*/LicenseContentProvider\.java",
1903 r".*/PlatformServiceBridgeImpl.java",
1904 r".*chrome/android/feed/dummy/.*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021905]
[email protected]127f18ec2012-06-16 05:05:591906
Mohamed Heikald048240a2019-11-12 16:57:371907# List of image extensions that are used as resources in chromium.
1908_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1909
Sean Kau46e29bc2017-08-28 16:31:161910# These paths contain test data and other known invalid JSON files.
Erik Staab2dd72b12020-04-16 15:03:401911_KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS = [
Bruce Dawson40fece62022-09-16 19:58:311912 r'test/data/',
1913 r'testing/buildbot/',
1914 r'^components/policy/resources/policy_templates\.json$',
1915 r'^third_party/protobuf/',
Camillo Bruni1411a352023-05-24 12:39:031916 r'^third_party/blink/perf_tests/speedometer.*/resources/todomvc/learn\.json',
Bruce Dawson40fece62022-09-16 19:58:311917 r'^third_party/blink/renderer/devtools/protocol\.json$',
1918 r'^third_party/blink/web_tests/external/wpt/',
1919 r'^tools/perf/',
1920 r'^tools/traceline/svgui/startup-release.json',
Daniel Cheng2d4c2d192022-07-01 01:38:311921 # vscode configuration files allow comments
Bruce Dawson40fece62022-09-16 19:58:311922 r'^tools/vscode/',
Sean Kau46e29bc2017-08-28 16:31:161923]
1924
Andrew Grieveb773bad2020-06-05 18:00:381925# These are not checked on the public chromium-presubmit trybot.
1926# Add files here that rely on .py files that exists only for target_os="android"
Samuel Huangc2f5d6bb2020-08-17 23:46:041927# checkouts.
agrievef32bcc72016-04-04 14:57:401928_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Grieveb773bad2020-06-05 18:00:381929 'chrome/android/features/create_stripped_java_factory.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:381930]
1931
1932
1933_GENERIC_PYDEPS_FILES = [
Bruce Dawson853b739e62022-05-03 23:03:101934 'android_webview/test/components/run_webview_component_smoketest.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:041935 'android_webview/tools/run_cts.pydeps',
Andrew Grieve4c4cede2020-11-20 22:09:361936 'build/android/apk_operations.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:041937 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361938 'build/android/gyp/aar.pydeps',
1939 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271940 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361941 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381942 'build/android/gyp/assert_static_initializers.pydeps',
Mohamed Heikal133e1f22023-04-18 20:04:371943 'build/android/gyp/binary_baseline_profile.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361944 'build/android/gyp/bytecode_processor.pydeps',
Robbie McElrath360e54d2020-11-12 20:38:021945 'build/android/gyp/bytecode_rewriter.pydeps',
Mohamed Heikal6305bcc2021-03-15 15:34:221946 'build/android/gyp/check_flag_expectations.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111947 'build/android/gyp/compile_java.pydeps',
Peter Weneaa963f2023-01-20 19:40:301948 'build/android/gyp/compile_kt.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361949 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361950 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361951 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111952 'build/android/gyp/create_app_bundle.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:041953 'build/android/gyp/create_app_bundle_apks.pydeps',
1954 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361955 'build/android/gyp/create_java_binary_script.pydeps',
Mohamed Heikaladbe4e482020-07-09 19:25:121956 'build/android/gyp/create_r_java.pydeps',
Mohamed Heikal8cd763a52021-02-01 23:32:091957 'build/android/gyp/create_r_txt.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221958 'build/android/gyp/create_size_info_files.pydeps',
Peter Wene6e017e2022-07-27 21:40:401959 'build/android/gyp/create_test_apk_wrapper_script.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:001960 'build/android/gyp/create_ui_locale_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361961 'build/android/gyp/dex.pydeps',
1962 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361963 'build/android/gyp/filter_zip.pydeps',
Mohamed Heikal21e1994b2021-11-12 21:37:211964 'build/android/gyp/flatc_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361965 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361966 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361967 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581968 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361969 'build/android/gyp/java_cpp_enum.pydeps',
Nate Fischerac07b2622020-10-01 20:20:141970 'build/android/gyp/java_cpp_features.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261971 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve09457912021-04-27 15:22:471972 'build/android/gyp/java_google_api_keys.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:041973 'build/android/gyp/jinja_template.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361974 'build/android/gyp/lint.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361975 'build/android/gyp/merge_manifest.pydeps',
Bruce Dawson853b739e62022-05-03 23:03:101976 'build/android/gyp/optimize_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361977 'build/android/gyp/prepare_resources.pydeps',
Mohamed Heikalf85138b2020-10-06 15:43:221978 'build/android/gyp/process_native_prebuilt.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361979 'build/android/gyp/proguard.pydeps',
Andrew Grievee3a775ab2022-05-16 15:59:221980 'build/android/gyp/system_image_apks.pydeps',
Bruce Dawson853b739e62022-05-03 23:03:101981 'build/android/gyp/trace_event_bytecode_rewriter.pydeps',
Peter Wen578730b2020-03-19 19:55:461982 'build/android/gyp/turbine.pydeps',
Mohamed Heikal246710c2021-06-14 15:34:301983 'build/android/gyp/unused_resources.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241984 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361985 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461986 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561987 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361988 'build/android/incremental_install/generate_android_manifest.pydeps',
1989 'build/android/incremental_install/write_installer_json.pydeps',
Stephanie Kim392913b452022-06-15 17:25:321990 'build/android/pylib/results/presentation/test_results_presentation.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:041991 'build/android/resource_sizes.pydeps',
1992 'build/android/test_runner.pydeps',
1993 'build/android/test_wrapper/logdog_wrapper.pydeps',
Samuel Huange65eb3f12020-08-14 19:04:361994 'build/lacros/lacros_resource_sizes.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361995 'build/protoc_java.pydeps',
Peter Kotwicz64667b02020-10-18 06:43:321996 'chrome/android/monochrome/scripts/monochrome_python_tests.pydeps',
Peter Wenefb56c72020-06-04 15:12:271997 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
1998 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Junbo Kedcd3a452021-03-19 17:55:041999 'chromecast/resource_sizes/chromecast_resource_sizes.pydeps',
Mohannad Farrag19102742023-12-01 01:16:302000 'components/cronet/tools/check_combined_proguard_file.pydeps',
2001 'components/cronet/tools/generate_proguard_file.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:002002 'components/cronet/tools/generate_javadoc.pydeps',
2003 'components/cronet/tools/jar_src.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:382004 'components/module_installer/android/module_desc_java.pydeps',
Andrew Grieve5a01ad32020-06-25 18:06:002005 'content/public/android/generate_child_service.pydeps',
Andrew Grieveb773bad2020-06-05 18:00:382006 'net/tools/testserver/testserver.pydeps',
Peter Kotwicz3c339f32020-10-19 19:59:182007 'testing/scripts/run_isolated_script_test.pydeps',
Stephanie Kimc94072c2022-03-22 22:31:412008 'testing/merge_scripts/standard_isolated_script_merge.pydeps',
2009 'testing/merge_scripts/standard_gtest_merge.pydeps',
2010 'testing/merge_scripts/code_coverage/merge_results.pydeps',
2011 'testing/merge_scripts/code_coverage/merge_steps.pydeps',
Samuel Huangc2f5d6bb2020-08-17 23:46:042012 'third_party/android_platform/development/scripts/stack.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:422013 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
Yuki Shiino38eeaad12022-08-11 06:40:252014 'third_party/blink/renderer/bindings/scripts/check_generated_file_list.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:422015 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:132016 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Yuki Shiinoea477d32023-08-21 06:24:342017 'third_party/blink/renderer/bindings/scripts/generate_event_interface_names.pydeps',
Canon Mukaif32f8f592021-04-23 18:56:502018 'third_party/blink/renderer/bindings/scripts/validate_web_idl.pydeps',
Stephanie Kimc94072c2022-03-22 22:31:412019 'third_party/blink/tools/blinkpy/web_tests/merge_results.pydeps',
2020 'third_party/blink/tools/merge_web_test_results.pydeps',
John Budorickbc3571aa2019-04-25 02:20:062021 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:222022 'tools/binary_size/supersize.pydeps',
Ben Pastene028104a2022-08-10 19:17:452023 'tools/perf/process_perf_results.pydeps',
agrievef32bcc72016-04-04 14:57:402024]
2025
wnwenbdc444e2016-05-25 13:44:152026
agrievef32bcc72016-04-04 14:57:402027_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
2028
2029
Eric Boren6fd2b932018-01-25 15:05:082030# Bypass the AUTHORS check for these accounts.
2031_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:592032 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:452033 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:592034 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:522035 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
Sven Zhengf7abd31d2021-08-09 19:06:232036 'wpt-autoroller', 'chrome-weblayer-builder',
Garrett Beaty4d4fcf62021-11-24 17:57:472037 'lacros-version-skew-roller', 'skylab-test-cros-roller',
Sven Zheng722960ba2022-07-18 16:40:462038 'infra-try-recipes-tester', 'lacros-tracking-roller',
Brian Sheedy1c951e62022-10-27 01:16:182039 'lacros-sdk-version-roller', 'chrome-automated-expectation',
Stephanie Kimb49bdd242023-04-28 16:46:042040 'chromium-automated-expectation', 'chrome-branch-day',
2041 'chromium-autosharder')
Eric Boren835d71f2018-09-07 21:09:042042 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:272043 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:042044 ) | set('%[email protected]' % s
Yulan Lineb0cfba2021-04-09 18:43:162045 for s in ('chromium-internal-autoroll',)
2046 ) | set('%[email protected]' % s
Chong Gub277e342022-10-15 03:30:552047 for s in ('swarming-tasks',)
2048 ) | set('%[email protected]' % s
2049 for s in ('global-integration-try-builder',
Joey Scarr1103c5d2023-09-14 01:17:552050 'global-integration-ci-builder')
Suma Kasa3b9cf7a2023-09-21 22:05:542051 ) | set('%[email protected]' % s
2052 for s in ('chops-security-borg',
2053 'chops-security-cronjobs-cpesuggest'))
Eric Boren6fd2b932018-01-25 15:05:082054
Matt Stark6ef08872021-07-29 01:21:462055_INVALID_GRD_FILE_LINE = [
2056 (r'<file lang=.* path=.*', 'Path should come before lang in GRD files.')
2057]
Eric Boren6fd2b932018-01-25 15:05:082058
Daniel Bratell65b033262019-04-23 08:17:062059def _IsCPlusPlusFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502060 """Returns True if this file contains C++-like code (and not Python,
2061 Go, Java, MarkDown, ...)"""
Daniel Bratell65b033262019-04-23 08:17:062062
Sam Maiera6e76d72022-02-11 21:43:502063 ext = input_api.os_path.splitext(file_path)[1]
2064 # This list is compatible with CppChecker.IsCppFile but we should
2065 # consider adding ".c" to it. If we do that we can use this function
2066 # at more places in the code.
2067 return ext in (
2068 '.h',
2069 '.cc',
2070 '.cpp',
2071 '.m',
2072 '.mm',
2073 )
2074
Daniel Bratell65b033262019-04-23 08:17:062075
2076def _IsCPlusPlusHeaderFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502077 return input_api.os_path.splitext(file_path)[1] == ".h"
Daniel Bratell65b033262019-04-23 08:17:062078
2079
2080def _IsJavaFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502081 return input_api.os_path.splitext(file_path)[1] == ".java"
Daniel Bratell65b033262019-04-23 08:17:062082
2083
2084def _IsProtoFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502085 return input_api.os_path.splitext(file_path)[1] == ".proto"
Daniel Bratell65b033262019-04-23 08:17:062086
Mohamed Heikal5e5b7922020-10-29 18:57:592087
Erik Staabc734cd7a2021-11-23 03:11:522088def _IsXmlOrGrdFile(input_api, file_path):
Sam Maiera6e76d72022-02-11 21:43:502089 ext = input_api.os_path.splitext(file_path)[1]
2090 return ext in ('.grd', '.xml')
Erik Staabc734cd7a2021-11-23 03:11:522091
2092
Sven Zheng76a79ea2022-12-21 21:25:242093def _IsMojomFile(input_api, file_path):
2094 return input_api.os_path.splitext(file_path)[1] == ".mojom"
2095
2096
Mohamed Heikal5e5b7922020-10-29 18:57:592097def CheckNoUpstreamDepsOnClank(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502098 """Prevent additions of dependencies from the upstream repo on //clank."""
2099 # clank can depend on clank
2100 if input_api.change.RepositoryRoot().endswith('clank'):
2101 return []
2102 build_file_patterns = [
2103 r'(.+/)?BUILD\.gn',
2104 r'.+\.gni',
2105 ]
2106 excluded_files = [r'build[/\\]config[/\\]android[/\\]config\.gni']
2107 bad_pattern = input_api.re.compile(r'^[^#]*//clank')
Mohamed Heikal5e5b7922020-10-29 18:57:592108
Sam Maiera6e76d72022-02-11 21:43:502109 error_message = 'Disallowed import on //clank in an upstream build file:'
Mohamed Heikal5e5b7922020-10-29 18:57:592110
Sam Maiera6e76d72022-02-11 21:43:502111 def FilterFile(affected_file):
2112 return input_api.FilterSourceFile(affected_file,
2113 files_to_check=build_file_patterns,
2114 files_to_skip=excluded_files)
Mohamed Heikal5e5b7922020-10-29 18:57:592115
Sam Maiera6e76d72022-02-11 21:43:502116 problems = []
2117 for f in input_api.AffectedSourceFiles(FilterFile):
2118 local_path = f.LocalPath()
2119 for line_number, line in f.ChangedContents():
2120 if (bad_pattern.search(line)):
2121 problems.append('%s:%d\n %s' %
2122 (local_path, line_number, line.strip()))
2123 if problems:
2124 return [output_api.PresubmitPromptOrNotify(error_message, problems)]
2125 else:
2126 return []
Mohamed Heikal5e5b7922020-10-29 18:57:592127
2128
Saagar Sanghavifceeaae2020-08-12 16:40:362129def CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502130 """Attempts to prevent use of functions intended only for testing in
2131 non-testing code. For now this is just a best-effort implementation
2132 that ignores header files and may have some false positives. A
2133 better implementation would probably need a proper C++ parser.
2134 """
2135 # We only scan .cc files and the like, as the declaration of
2136 # for-testing functions in header files are hard to distinguish from
2137 # calls to such functions without a proper C++ parser.
2138 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:192139
Sam Maiera6e76d72022-02-11 21:43:502140 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
2141 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' %
2142 base_function_pattern)
2143 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
2144 allowlist_pattern = input_api.re.compile(r'// IN-TEST$')
2145 exclusion_pattern = input_api.re.compile(
2146 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' %
2147 (base_function_pattern, base_function_pattern))
2148 # Avoid a false positive in this case, where the method name, the ::, and
2149 # the closing { are all on different lines due to line wrapping.
2150 # HelperClassForTesting::
2151 # HelperClassForTesting(
2152 # args)
2153 # : member(0) {}
2154 method_defn_pattern = input_api.re.compile(r'[A-Za-z0-9_]+::$')
[email protected]55459852011-08-10 15:17:192155
Sam Maiera6e76d72022-02-11 21:43:502156 def FilterFile(affected_file):
2157 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2158 input_api.DEFAULT_FILES_TO_SKIP)
2159 return input_api.FilterSourceFile(
2160 affected_file,
2161 files_to_check=file_inclusion_pattern,
2162 files_to_skip=files_to_skip)
[email protected]55459852011-08-10 15:17:192163
Sam Maiera6e76d72022-02-11 21:43:502164 problems = []
2165 for f in input_api.AffectedSourceFiles(FilterFile):
2166 local_path = f.LocalPath()
2167 in_method_defn = False
2168 for line_number, line in f.ChangedContents():
2169 if (inclusion_pattern.search(line)
2170 and not comment_pattern.search(line)
2171 and not exclusion_pattern.search(line)
2172 and not allowlist_pattern.search(line)
2173 and not in_method_defn):
2174 problems.append('%s:%d\n %s' %
2175 (local_path, line_number, line.strip()))
2176 in_method_defn = method_defn_pattern.search(line)
[email protected]55459852011-08-10 15:17:192177
Sam Maiera6e76d72022-02-11 21:43:502178 if problems:
2179 return [
2180 output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)
2181 ]
2182 else:
2183 return []
[email protected]55459852011-08-10 15:17:192184
2185
Saagar Sanghavifceeaae2020-08-12 16:40:362186def CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502187 """This is a simplified version of
2188 CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
2189 """
2190 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
2191 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
2192 name_pattern = r'ForTest(s|ing)?'
2193 # Describes an occurrence of "ForTest*" inside a // comment.
2194 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
2195 # Describes @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
2196 annotation_re = input_api.re.compile(r'@VisibleForTesting\(')
2197 # Catch calls.
2198 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
2199 # Ignore definitions. (Comments are ignored separately.)
2200 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
Andrew Grieve40f451d2023-07-06 19:46:512201 allowlist_re = input_api.re.compile(r'// IN-TEST$')
Vaclav Brozek7dbc28c2018-03-27 08:35:232202
Sam Maiera6e76d72022-02-11 21:43:502203 problems = []
2204 sources = lambda x: input_api.FilterSourceFile(
2205 x,
2206 files_to_skip=(('(?i).*test', r'.*\/junit\/') + input_api.
2207 DEFAULT_FILES_TO_SKIP),
2208 files_to_check=[r'.*\.java$'])
2209 for f in input_api.AffectedFiles(include_deletes=False,
2210 file_filter=sources):
2211 local_path = f.LocalPath()
Vaclav Brozek7dbc28c2018-03-27 08:35:232212 is_inside_javadoc = False
Sam Maiera6e76d72022-02-11 21:43:502213 for line_number, line in f.ChangedContents():
2214 if is_inside_javadoc and javadoc_end_re.search(line):
2215 is_inside_javadoc = False
2216 if not is_inside_javadoc and javadoc_start_re.search(line):
2217 is_inside_javadoc = True
2218 if is_inside_javadoc:
2219 continue
2220 if (inclusion_re.search(line) and not comment_re.search(line)
2221 and not annotation_re.search(line)
Andrew Grieve40f451d2023-07-06 19:46:512222 and not allowlist_re.search(line)
Sam Maiera6e76d72022-02-11 21:43:502223 and not exclusion_re.search(line)):
2224 problems.append('%s:%d\n %s' %
2225 (local_path, line_number, line.strip()))
Vaclav Brozek7dbc28c2018-03-27 08:35:232226
Sam Maiera6e76d72022-02-11 21:43:502227 if problems:
2228 return [
2229 output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)
2230 ]
2231 else:
2232 return []
Vaclav Brozek7dbc28c2018-03-27 08:35:232233
2234
Saagar Sanghavifceeaae2020-08-12 16:40:362235def CheckNoIOStreamInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502236 """Checks to make sure no .h files include <iostream>."""
2237 files = []
2238 pattern = input_api.re.compile(r'^#include\s*<iostream>',
2239 input_api.re.MULTILINE)
2240 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2241 if not f.LocalPath().endswith('.h'):
2242 continue
2243 contents = input_api.ReadFile(f)
2244 if pattern.search(contents):
2245 files.append(f)
[email protected]10689ca2011-09-02 02:31:542246
Sam Maiera6e76d72022-02-11 21:43:502247 if len(files):
2248 return [
2249 output_api.PresubmitError(
2250 'Do not #include <iostream> in header files, since it inserts static '
2251 'initialization into every file including the header. Instead, '
2252 '#include <ostream>. See http://crbug.com/94794', files)
2253 ]
2254 return []
2255
[email protected]10689ca2011-09-02 02:31:542256
Aleksey Khoroshilov9b28c032022-06-03 16:35:322257def CheckNoStrCatRedefines(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502258 """Checks no windows headers with StrCat redefined are included directly."""
2259 files = []
Aleksey Khoroshilov9b28c032022-06-03 16:35:322260 files_to_check = (r'.+%s' % _HEADER_EXTENSIONS,
2261 r'.+%s' % _IMPLEMENTATION_EXTENSIONS)
2262 files_to_skip = (input_api.DEFAULT_FILES_TO_SKIP +
2263 _NON_BASE_DEPENDENT_PATHS)
2264 sources_filter = lambda f: input_api.FilterSourceFile(
2265 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
2266
Sam Maiera6e76d72022-02-11 21:43:502267 pattern_deny = input_api.re.compile(
2268 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
2269 input_api.re.MULTILINE)
2270 pattern_allow = input_api.re.compile(
2271 r'^#include\s"base/win/windows_defines.inc"', input_api.re.MULTILINE)
Aleksey Khoroshilov9b28c032022-06-03 16:35:322272 for f in input_api.AffectedSourceFiles(sources_filter):
Sam Maiera6e76d72022-02-11 21:43:502273 contents = input_api.ReadFile(f)
2274 if pattern_deny.search(
2275 contents) and not pattern_allow.search(contents):
2276 files.append(f.LocalPath())
Danil Chapovalov3518f362018-08-11 16:13:432277
Sam Maiera6e76d72022-02-11 21:43:502278 if len(files):
2279 return [
2280 output_api.PresubmitError(
2281 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
2282 'directly since they pollute code with StrCat macro. Instead, '
2283 'include matching header from base/win. See http://crbug.com/856536',
2284 files)
2285 ]
2286 return []
Danil Chapovalov3518f362018-08-11 16:13:432287
[email protected]10689ca2011-09-02 02:31:542288
Andrew Williamsc9f69b482023-07-10 16:07:362289def _CheckNoUNIT_TESTInSourceFiles(input_api, f):
2290 problems = []
2291
2292 unit_test_macro = input_api.re.compile(
2293 '^\s*#.*(?:ifn?def\s+UNIT_TEST|defined\s*\(?\s*UNIT_TEST\s*\)?)(?:$|\s+)')
2294 for line_num, line in f.ChangedContents():
2295 if unit_test_macro.match(line):
2296 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2297
2298 return problems
2299
2300
Saagar Sanghavifceeaae2020-08-12 16:40:362301def CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502302 """Checks to make sure no source files use UNIT_TEST."""
2303 problems = []
2304 for f in input_api.AffectedFiles():
2305 if (not f.LocalPath().endswith(('.cc', '.mm'))):
2306 continue
Andrew Williamsc9f69b482023-07-10 16:07:362307 problems.extend(
2308 _CheckNoUNIT_TESTInSourceFiles(input_api, f))
[email protected]72df4e782012-06-21 16:28:182309
Sam Maiera6e76d72022-02-11 21:43:502310 if not problems:
2311 return []
2312 return [
2313 output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
2314 '\n'.join(problems))
2315 ]
2316
[email protected]72df4e782012-06-21 16:28:182317
Saagar Sanghavifceeaae2020-08-12 16:40:362318def CheckNoDISABLETypoInTests(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502319 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
Dominic Battre033531052018-09-24 15:45:342320
Sam Maiera6e76d72022-02-11 21:43:502321 This test warns if somebody tries to disable a test with the DISABLE_ prefix
2322 instead of DISABLED_. To filter false positives, reports are only generated
2323 if a corresponding MAYBE_ line exists.
2324 """
2325 problems = []
Dominic Battre033531052018-09-24 15:45:342326
Sam Maiera6e76d72022-02-11 21:43:502327 # The following two patterns are looked for in tandem - is a test labeled
2328 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
2329 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
2330 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
Dominic Battre033531052018-09-24 15:45:342331
Sam Maiera6e76d72022-02-11 21:43:502332 # This is for the case that a test is disabled on all platforms.
2333 full_disable_pattern = input_api.re.compile(
2334 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
2335 input_api.re.MULTILINE)
Dominic Battre033531052018-09-24 15:45:342336
Sam Maiera6e76d72022-02-11 21:43:502337 for f in input_api.AffectedFiles(False):
2338 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
2339 continue
Dominic Battre033531052018-09-24 15:45:342340
Sam Maiera6e76d72022-02-11 21:43:502341 # Search for MABYE_, DISABLE_ pairs.
2342 disable_lines = {} # Maps of test name to line number.
2343 maybe_lines = {}
2344 for line_num, line in f.ChangedContents():
2345 disable_match = disable_pattern.search(line)
2346 if disable_match:
2347 disable_lines[disable_match.group(1)] = line_num
2348 maybe_match = maybe_pattern.search(line)
2349 if maybe_match:
2350 maybe_lines[maybe_match.group(1)] = line_num
Dominic Battre033531052018-09-24 15:45:342351
Sam Maiera6e76d72022-02-11 21:43:502352 # Search for DISABLE_ occurrences within a TEST() macro.
2353 disable_tests = set(disable_lines.keys())
2354 maybe_tests = set(maybe_lines.keys())
2355 for test in disable_tests.intersection(maybe_tests):
2356 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
Dominic Battre033531052018-09-24 15:45:342357
Sam Maiera6e76d72022-02-11 21:43:502358 contents = input_api.ReadFile(f)
2359 full_disable_match = full_disable_pattern.search(contents)
2360 if full_disable_match:
2361 problems.append(' %s' % f.LocalPath())
Dominic Battre033531052018-09-24 15:45:342362
Sam Maiera6e76d72022-02-11 21:43:502363 if not problems:
2364 return []
2365 return [
2366 output_api.PresubmitPromptWarning(
2367 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
2368 '\n'.join(problems))
2369 ]
2370
Dominic Battre033531052018-09-24 15:45:342371
Nina Satragnof7660532021-09-20 18:03:352372def CheckForgettingMAYBEInTests(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502373 """Checks to make sure tests disabled conditionally are not missing a
2374 corresponding MAYBE_ prefix.
2375 """
2376 # Expect at least a lowercase character in the test name. This helps rule out
2377 # false positives with macros wrapping the actual tests name.
2378 define_maybe_pattern = input_api.re.compile(
2379 r'^\#define MAYBE_(?P<test_name>\w*[a-z]\w*)')
Bruce Dawsonffc55292022-04-20 04:18:192380 # The test_maybe_pattern needs to handle all of these forms. The standard:
2381 # IN_PROC_TEST_F(SyncTest, MAYBE_Start) {
2382 # With a wrapper macro around the test name:
2383 # IN_PROC_TEST_F(SyncTest, E2E_ENABLED(MAYBE_Start)) {
2384 # And the odd-ball NACL_BROWSER_TEST_f format:
2385 # NACL_BROWSER_TEST_F(NaClBrowserTest, SimpleLoad, {
2386 # The optional E2E_ENABLED-style is handled with (\w*\()?
2387 # The NACL_BROWSER_TEST_F pattern is handled by allowing a trailing comma or
2388 # trailing ')'.
2389 test_maybe_pattern = (
2390 r'^\s*\w*TEST[^(]*\(\s*\w+,\s*(\w*\()?MAYBE_{test_name}[\),]')
Sam Maiera6e76d72022-02-11 21:43:502391 suite_maybe_pattern = r'^\s*\w*TEST[^(]*\(\s*MAYBE_{test_name}[\),]'
2392 warnings = []
Nina Satragnof7660532021-09-20 18:03:352393
Sam Maiera6e76d72022-02-11 21:43:502394 # Read the entire files. We can't just read the affected lines, forgetting to
2395 # add MAYBE_ on a change would not show up otherwise.
2396 for f in input_api.AffectedFiles(False):
2397 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
2398 continue
2399 contents = input_api.ReadFile(f)
2400 lines = contents.splitlines(True)
2401 current_position = 0
2402 warning_test_names = set()
2403 for line_num, line in enumerate(lines, start=1):
2404 current_position += len(line)
2405 maybe_match = define_maybe_pattern.search(line)
2406 if maybe_match:
2407 test_name = maybe_match.group('test_name')
2408 # Do not warn twice for the same test.
2409 if (test_name in warning_test_names):
2410 continue
2411 warning_test_names.add(test_name)
Nina Satragnof7660532021-09-20 18:03:352412
Sam Maiera6e76d72022-02-11 21:43:502413 # Attempt to find the corresponding MAYBE_ test or suite, starting from
2414 # the current position.
2415 test_match = input_api.re.compile(
2416 test_maybe_pattern.format(test_name=test_name),
2417 input_api.re.MULTILINE).search(contents, current_position)
2418 suite_match = input_api.re.compile(
2419 suite_maybe_pattern.format(test_name=test_name),
2420 input_api.re.MULTILINE).search(contents, current_position)
2421 if not test_match and not suite_match:
2422 warnings.append(
2423 output_api.PresubmitPromptWarning(
2424 '%s:%d found MAYBE_ defined without corresponding test %s'
2425 % (f.LocalPath(), line_num, test_name)))
2426 return warnings
2427
[email protected]72df4e782012-06-21 16:28:182428
Saagar Sanghavifceeaae2020-08-12 16:40:362429def CheckDCHECK_IS_ONHasBraces(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502430 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
2431 errors = []
Kalvin Lee4a3b79de2022-05-26 16:00:162432 pattern = input_api.re.compile(r'\bDCHECK_IS_ON\b(?!\(\))',
Sam Maiera6e76d72022-02-11 21:43:502433 input_api.re.MULTILINE)
2434 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2435 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
2436 continue
2437 for lnum, line in f.ChangedContents():
2438 if input_api.re.search(pattern, line):
2439 errors.append(
2440 output_api.PresubmitError((
2441 '%s:%d: Use of DCHECK_IS_ON() must be written as "#if '
2442 + 'DCHECK_IS_ON()", not forgetting the parentheses.') %
2443 (f.LocalPath(), lnum)))
2444 return errors
danakj61c1aa22015-10-26 19:55:522445
2446
Weilun Shia487fad2020-10-28 00:10:342447# TODO(crbug/1138055): Reimplement CheckUmaHistogramChangesOnUpload check in a
2448# more reliable way. See
2449# https://chromium-review.googlesource.com/c/chromium/src/+/2500269
mcasasb7440c282015-02-04 14:52:192450
wnwenbdc444e2016-05-25 13:44:152451
Saagar Sanghavifceeaae2020-08-12 16:40:362452def CheckFlakyTestUsage(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502453 """Check that FlakyTest annotation is our own instead of the android one"""
2454 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
2455 files = []
2456 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2457 if f.LocalPath().endswith('Test.java'):
2458 if pattern.search(input_api.ReadFile(f)):
2459 files.append(f)
2460 if len(files):
2461 return [
2462 output_api.PresubmitError(
2463 'Use org.chromium.base.test.util.FlakyTest instead of '
2464 'android.test.FlakyTest', files)
2465 ]
2466 return []
mcasasb7440c282015-02-04 14:52:192467
wnwenbdc444e2016-05-25 13:44:152468
Saagar Sanghavifceeaae2020-08-12 16:40:362469def CheckNoDEPSGIT(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502470 """Make sure .DEPS.git is never modified manually."""
2471 if any(f.LocalPath().endswith('.DEPS.git')
2472 for f in input_api.AffectedFiles()):
2473 return [
2474 output_api.PresubmitError(
2475 'Never commit changes to .DEPS.git. This file is maintained by an\n'
2476 'automated system based on what\'s in DEPS and your changes will be\n'
2477 'overwritten.\n'
2478 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
2479 'get-the-code#Rolling_DEPS\n'
2480 'for more information')
2481 ]
2482 return []
[email protected]2a8ac9c2011-10-19 17:20:442483
2484
Sven Zheng76a79ea2022-12-21 21:25:242485def CheckCrosApiNeedBrowserTest(input_api, output_api):
2486 """Check new crosapi should add browser test."""
2487 has_new_crosapi = False
2488 has_browser_test = False
2489 for f in input_api.AffectedFiles():
2490 path = f.LocalPath()
2491 if (path.startswith('chromeos/crosapi/mojom') and
2492 _IsMojomFile(input_api, path) and f.Action() == 'A'):
2493 has_new_crosapi = True
2494 if path.endswith('browsertest.cc') or path.endswith('browser_test.cc'):
2495 has_browser_test = True
2496 if has_new_crosapi and not has_browser_test:
2497 return [
2498 output_api.PresubmitPromptWarning(
2499 'You are adding a new crosapi, but there is no file ends with '
2500 'browsertest.cc file being added or modified. It is important '
2501 'to add crosapi browser test coverage to avoid version '
2502 ' skew issues.\n'
2503 'Check //docs/lacros/test_instructions.md for more information.'
2504 )
2505 ]
2506 return []
2507
2508
Saagar Sanghavifceeaae2020-08-12 16:40:362509def CheckValidHostsInDEPSOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502510 """Checks that DEPS file deps are from allowed_hosts."""
2511 # Run only if DEPS file has been modified to annoy fewer bystanders.
2512 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
2513 return []
2514 # Outsource work to gclient verify
2515 try:
2516 gclient_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
2517 'third_party', 'depot_tools',
2518 'gclient.py')
2519 input_api.subprocess.check_output(
Bruce Dawson8a43cf72022-05-13 17:10:322520 [input_api.python3_executable, gclient_path, 'verify'],
Sam Maiera6e76d72022-02-11 21:43:502521 stderr=input_api.subprocess.STDOUT)
2522 return []
2523 except input_api.subprocess.CalledProcessError as error:
2524 return [
2525 output_api.PresubmitError(
2526 'DEPS file must have only git dependencies.',
2527 long_text=error.output)
2528 ]
tandriief664692014-09-23 14:51:472529
2530
Mario Sanchez Prada2472cab2019-09-18 10:58:312531def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
Daniel Chenga44a1bcd2022-03-15 20:00:152532 ban_rule):
Allen Bauer84778682022-09-22 16:28:562533 """Helper method for checking for banned constructs.
Mario Sanchez Prada2472cab2019-09-18 10:58:312534
Sam Maiera6e76d72022-02-11 21:43:502535 Returns an string composed of the name of the file, the line number where the
2536 match has been found and the additional text passed as |message| in case the
2537 target type name matches the text inside the line passed as parameter.
2538 """
2539 result = []
Peng Huang9c5949a02020-06-11 19:20:542540
Daniel Chenga44a1bcd2022-03-15 20:00:152541 # Ignore comments about banned types.
2542 if input_api.re.search(r"^ *//", line):
Sam Maiera6e76d72022-02-11 21:43:502543 return result
Daniel Chenga44a1bcd2022-03-15 20:00:152544 # A // nocheck comment will bypass this error.
2545 if line.endswith(" nocheck"):
Sam Maiera6e76d72022-02-11 21:43:502546 return result
2547
2548 matched = False
Daniel Chenga44a1bcd2022-03-15 20:00:152549 if ban_rule.pattern[0:1] == '/':
2550 regex = ban_rule.pattern[1:]
Sam Maiera6e76d72022-02-11 21:43:502551 if input_api.re.search(regex, line):
2552 matched = True
Daniel Chenga44a1bcd2022-03-15 20:00:152553 elif ban_rule.pattern in line:
Sam Maiera6e76d72022-02-11 21:43:502554 matched = True
2555
2556 if matched:
2557 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
Daniel Chenga44a1bcd2022-03-15 20:00:152558 for line in ban_rule.explanation:
2559 result.append(' %s' % line)
Sam Maiera6e76d72022-02-11 21:43:502560
danakjd18e8892020-12-17 17:42:012561 return result
Mario Sanchez Prada2472cab2019-09-18 10:58:312562
2563
Saagar Sanghavifceeaae2020-08-12 16:40:362564def CheckNoBannedFunctions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502565 """Make sure that banned functions are not used."""
2566 warnings = []
2567 errors = []
[email protected]127f18ec2012-06-16 05:05:592568
Sam Maiera6e76d72022-02-11 21:43:502569 def IsExcludedFile(affected_file, excluded_paths):
Daniel Chenga44a1bcd2022-03-15 20:00:152570 if not excluded_paths:
2571 return False
2572
Sam Maiera6e76d72022-02-11 21:43:502573 local_path = affected_file.LocalPath()
Bruce Dawson40fece62022-09-16 19:58:312574 # Consistently use / as path separator to simplify the writing of regex
2575 # expressions.
2576 local_path = local_path.replace(input_api.os_path.sep, '/')
Sam Maiera6e76d72022-02-11 21:43:502577 for item in excluded_paths:
2578 if input_api.re.match(item, local_path):
2579 return True
2580 return False
wnwenbdc444e2016-05-25 13:44:152581
Sam Maiera6e76d72022-02-11 21:43:502582 def IsIosObjcFile(affected_file):
2583 local_path = affected_file.LocalPath()
2584 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m',
2585 '.h'):
2586 return False
2587 basename = input_api.os_path.basename(local_path)
2588 if 'ios' in basename.split('_'):
2589 return True
2590 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
2591 if sep and 'ios' in local_path.split(sep):
2592 return True
2593 return False
Sylvain Defresnea8b73d252018-02-28 15:45:542594
Daniel Chenga44a1bcd2022-03-15 20:00:152595 def CheckForMatch(affected_file, line_num: int, line: str,
2596 ban_rule: BanRule):
2597 if IsExcludedFile(affected_file, ban_rule.excluded_paths):
2598 return
2599
Sam Maiera6e76d72022-02-11 21:43:502600 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
Daniel Chenga44a1bcd2022-03-15 20:00:152601 ban_rule)
Sam Maiera6e76d72022-02-11 21:43:502602 if problems:
Daniel Chenga44a1bcd2022-03-15 20:00:152603 if ban_rule.treat_as_error is not None and ban_rule.treat_as_error:
Sam Maiera6e76d72022-02-11 21:43:502604 errors.extend(problems)
2605 else:
2606 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:152607
Sam Maiera6e76d72022-02-11 21:43:502608 file_filter = lambda f: f.LocalPath().endswith(('.java'))
2609 for f in input_api.AffectedFiles(file_filter=file_filter):
2610 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152611 for ban_rule in _BANNED_JAVA_FUNCTIONS:
2612 CheckForMatch(f, line_num, line, ban_rule)
Eric Stevensona9a980972017-09-23 00:04:412613
Clement Yan9b330cb2022-11-17 05:25:292614 file_filter = lambda f: f.LocalPath().endswith(('.js', '.ts'))
2615 for f in input_api.AffectedFiles(file_filter=file_filter):
2616 for line_num, line in f.ChangedContents():
2617 for ban_rule in _BANNED_JAVASCRIPT_FUNCTIONS:
2618 CheckForMatch(f, line_num, line, ban_rule)
2619
Sam Maiera6e76d72022-02-11 21:43:502620 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
2621 for f in input_api.AffectedFiles(file_filter=file_filter):
2622 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152623 for ban_rule in _BANNED_OBJC_FUNCTIONS:
2624 CheckForMatch(f, line_num, line, ban_rule)
[email protected]127f18ec2012-06-16 05:05:592625
Sam Maiera6e76d72022-02-11 21:43:502626 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
2627 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152628 for ban_rule in _BANNED_IOS_OBJC_FUNCTIONS:
2629 CheckForMatch(f, line_num, line, ban_rule)
Sylvain Defresnea8b73d252018-02-28 15:45:542630
Sam Maiera6e76d72022-02-11 21:43:502631 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
2632 for f in input_api.AffectedFiles(file_filter=egtest_filter):
2633 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152634 for ban_rule in _BANNED_IOS_EGTEST_FUNCTIONS:
2635 CheckForMatch(f, line_num, line, ban_rule)
Peter K. Lee6c03ccff2019-07-15 14:40:052636
Sam Maiera6e76d72022-02-11 21:43:502637 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
2638 for f in input_api.AffectedFiles(file_filter=file_filter):
2639 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152640 for ban_rule in _BANNED_CPP_FUNCTIONS:
2641 CheckForMatch(f, line_num, line, ban_rule)
[email protected]127f18ec2012-06-16 05:05:592642
Daniel Cheng92c15e32022-03-16 17:48:222643 file_filter = lambda f: f.LocalPath().endswith(('.mojom'))
2644 for f in input_api.AffectedFiles(file_filter=file_filter):
2645 for line_num, line in f.ChangedContents():
2646 for ban_rule in _BANNED_MOJOM_PATTERNS:
2647 CheckForMatch(f, line_num, line, ban_rule)
2648
2649
Sam Maiera6e76d72022-02-11 21:43:502650 result = []
2651 if (warnings):
2652 result.append(
2653 output_api.PresubmitPromptWarning('Banned functions were used.\n' +
2654 '\n'.join(warnings)))
2655 if (errors):
2656 result.append(
2657 output_api.PresubmitError('Banned functions were used.\n' +
2658 '\n'.join(errors)))
2659 return result
[email protected]127f18ec2012-06-16 05:05:592660
Michael Thiessen44457642020-02-06 00:24:152661def _CheckAndroidNoBannedImports(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502662 """Make sure that banned java imports are not used."""
2663 errors = []
Michael Thiessen44457642020-02-06 00:24:152664
Sam Maiera6e76d72022-02-11 21:43:502665 file_filter = lambda f: f.LocalPath().endswith(('.java'))
2666 for f in input_api.AffectedFiles(file_filter=file_filter):
2667 for line_num, line in f.ChangedContents():
Daniel Chenga44a1bcd2022-03-15 20:00:152668 for ban_rule in _BANNED_JAVA_IMPORTS:
2669 # Consider merging this into the above function. There is no
2670 # real difference anymore other than helping with a little
2671 # bit of boilerplate text. Doing so means things like
2672 # `treat_as_error` will also be uniformly handled.
Sam Maiera6e76d72022-02-11 21:43:502673 problems = _GetMessageForMatchingType(input_api, f, line_num,
Daniel Chenga44a1bcd2022-03-15 20:00:152674 line, ban_rule)
Sam Maiera6e76d72022-02-11 21:43:502675 if problems:
2676 errors.extend(problems)
2677 result = []
2678 if (errors):
2679 result.append(
2680 output_api.PresubmitError('Banned imports were used.\n' +
2681 '\n'.join(errors)))
2682 return result
Michael Thiessen44457642020-02-06 00:24:152683
2684
Saagar Sanghavifceeaae2020-08-12 16:40:362685def CheckNoPragmaOnce(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502686 """Make sure that banned functions are not used."""
2687 files = []
2688 pattern = input_api.re.compile(r'^#pragma\s+once', input_api.re.MULTILINE)
2689 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2690 if not f.LocalPath().endswith('.h'):
2691 continue
Bruce Dawson4c4c2922022-05-02 18:07:332692 if f.LocalPath().endswith('com_imported_mstscax.h'):
2693 continue
Sam Maiera6e76d72022-02-11 21:43:502694 contents = input_api.ReadFile(f)
2695 if pattern.search(contents):
2696 files.append(f)
[email protected]6c063c62012-07-11 19:11:062697
Sam Maiera6e76d72022-02-11 21:43:502698 if files:
2699 return [
2700 output_api.PresubmitError(
2701 'Do not use #pragma once in header files.\n'
2702 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
2703 files)
2704 ]
2705 return []
[email protected]6c063c62012-07-11 19:11:062706
[email protected]127f18ec2012-06-16 05:05:592707
Saagar Sanghavifceeaae2020-08-12 16:40:362708def CheckNoTrinaryTrueFalse(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502709 """Checks to make sure we don't introduce use of foo ? true : false."""
2710 problems = []
2711 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2712 for f in input_api.AffectedFiles():
2713 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2714 continue
[email protected]e7479052012-09-19 00:26:122715
Sam Maiera6e76d72022-02-11 21:43:502716 for line_num, line in f.ChangedContents():
2717 if pattern.match(line):
2718 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]e7479052012-09-19 00:26:122719
Sam Maiera6e76d72022-02-11 21:43:502720 if not problems:
2721 return []
2722 return [
2723 output_api.PresubmitPromptWarning(
2724 'Please consider avoiding the "? true : false" pattern if possible.\n'
2725 + '\n'.join(problems))
2726 ]
[email protected]e7479052012-09-19 00:26:122727
2728
Saagar Sanghavifceeaae2020-08-12 16:40:362729def CheckUnwantedDependencies(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502730 """Runs checkdeps on #include and import statements added in this
2731 change. Breaking - rules is an error, breaking ! rules is a
2732 warning.
2733 """
2734 # Return early if no relevant file types were modified.
2735 for f in input_api.AffectedFiles():
2736 path = f.LocalPath()
2737 if (_IsCPlusPlusFile(input_api, path) or _IsProtoFile(input_api, path)
2738 or _IsJavaFile(input_api, path)):
2739 break
[email protected]55f9f382012-07-31 11:02:182740 else:
Sam Maiera6e76d72022-02-11 21:43:502741 return []
rhalavati08acd232017-04-03 07:23:282742
Sam Maiera6e76d72022-02-11 21:43:502743 import sys
2744 # We need to wait until we have an input_api object and use this
2745 # roundabout construct to import checkdeps because this file is
2746 # eval-ed and thus doesn't have __file__.
2747 original_sys_path = sys.path
2748 try:
2749 sys.path = sys.path + [
2750 input_api.os_path.join(input_api.PresubmitLocalPath(),
2751 'buildtools', 'checkdeps')
2752 ]
2753 import checkdeps
2754 from rules import Rule
2755 finally:
2756 # Restore sys.path to what it was before.
2757 sys.path = original_sys_path
[email protected]55f9f382012-07-31 11:02:182758
Sam Maiera6e76d72022-02-11 21:43:502759 added_includes = []
2760 added_imports = []
2761 added_java_imports = []
2762 for f in input_api.AffectedFiles():
2763 if _IsCPlusPlusFile(input_api, f.LocalPath()):
2764 changed_lines = [line for _, line in f.ChangedContents()]
2765 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
2766 elif _IsProtoFile(input_api, f.LocalPath()):
2767 changed_lines = [line for _, line in f.ChangedContents()]
2768 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
2769 elif _IsJavaFile(input_api, f.LocalPath()):
2770 changed_lines = [line for _, line in f.ChangedContents()]
2771 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
Jinsuk Kim5a092672017-10-24 22:42:242772
Sam Maiera6e76d72022-02-11 21:43:502773 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
2774
2775 error_descriptions = []
2776 warning_descriptions = []
2777 error_subjects = set()
2778 warning_subjects = set()
2779
2780 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2781 added_includes):
2782 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
2783 description_with_path = '%s\n %s' % (path, rule_description)
2784 if rule_type == Rule.DISALLOW:
2785 error_descriptions.append(description_with_path)
2786 error_subjects.add("#includes")
2787 else:
2788 warning_descriptions.append(description_with_path)
2789 warning_subjects.add("#includes")
2790
2791 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2792 added_imports):
2793 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
2794 description_with_path = '%s\n %s' % (path, rule_description)
2795 if rule_type == Rule.DISALLOW:
2796 error_descriptions.append(description_with_path)
2797 error_subjects.add("imports")
2798 else:
2799 warning_descriptions.append(description_with_path)
2800 warning_subjects.add("imports")
2801
2802 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
2803 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
2804 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
2805 description_with_path = '%s\n %s' % (path, rule_description)
2806 if rule_type == Rule.DISALLOW:
2807 error_descriptions.append(description_with_path)
2808 error_subjects.add("imports")
2809 else:
2810 warning_descriptions.append(description_with_path)
2811 warning_subjects.add("imports")
2812
2813 results = []
2814 if error_descriptions:
2815 results.append(
2816 output_api.PresubmitError(
2817 'You added one or more %s that violate checkdeps rules.' %
2818 " and ".join(error_subjects), error_descriptions))
2819 if warning_descriptions:
2820 results.append(
2821 output_api.PresubmitPromptOrNotify(
2822 'You added one or more %s of files that are temporarily\n'
2823 'allowed but being removed. Can you avoid introducing the\n'
2824 '%s? See relevant DEPS file(s) for details and contacts.' %
2825 (" and ".join(warning_subjects), "/".join(warning_subjects)),
2826 warning_descriptions))
2827 return results
[email protected]55f9f382012-07-31 11:02:182828
2829
Saagar Sanghavifceeaae2020-08-12 16:40:362830def CheckFilePermissions(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502831 """Check that all files have their permissions properly set."""
2832 if input_api.platform == 'win32':
2833 return []
2834 checkperms_tool = input_api.os_path.join(input_api.PresubmitLocalPath(),
2835 'tools', 'checkperms',
2836 'checkperms.py')
2837 args = [
Bruce Dawson8a43cf72022-05-13 17:10:322838 input_api.python3_executable, checkperms_tool, '--root',
Sam Maiera6e76d72022-02-11 21:43:502839 input_api.change.RepositoryRoot()
2840 ]
2841 with input_api.CreateTemporaryFile() as file_list:
2842 for f in input_api.AffectedFiles():
2843 # checkperms.py file/directory arguments must be relative to the
2844 # repository.
2845 file_list.write((f.LocalPath() + '\n').encode('utf8'))
2846 file_list.close()
2847 args += ['--file-list', file_list.name]
2848 try:
2849 input_api.subprocess.check_output(args)
2850 return []
2851 except input_api.subprocess.CalledProcessError as error:
2852 return [
2853 output_api.PresubmitError('checkperms.py failed:',
2854 long_text=error.output.decode(
2855 'utf-8', 'ignore'))
2856 ]
[email protected]fbcafe5a2012-08-08 15:31:222857
2858
Saagar Sanghavifceeaae2020-08-12 16:40:362859def CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502860 """Makes sure we don't include ui/aura/window_property.h
2861 in header files.
2862 """
2863 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2864 errors = []
2865 for f in input_api.AffectedFiles():
2866 if not f.LocalPath().endswith('.h'):
2867 continue
2868 for line_num, line in f.ChangedContents():
2869 if pattern.match(line):
2870 errors.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]c8278b32012-10-30 20:35:492871
Sam Maiera6e76d72022-02-11 21:43:502872 results = []
2873 if errors:
2874 results.append(
2875 output_api.PresubmitError(
2876 'Header files should not include ui/aura/window_property.h',
2877 errors))
2878 return results
[email protected]c8278b32012-10-30 20:35:492879
2880
Omer Katzcc77ea92021-04-26 10:23:282881def CheckNoInternalHeapIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502882 """Makes sure we don't include any headers from
2883 third_party/blink/renderer/platform/heap/impl or
2884 third_party/blink/renderer/platform/heap/v8_wrapper from files outside of
2885 third_party/blink/renderer/platform/heap
2886 """
2887 impl_pattern = input_api.re.compile(
2888 r'^\s*#include\s*"third_party/blink/renderer/platform/heap/impl/.*"')
2889 v8_wrapper_pattern = input_api.re.compile(
2890 r'^\s*#include\s*"third_party/blink/renderer/platform/heap/v8_wrapper/.*"'
2891 )
Bruce Dawson40fece62022-09-16 19:58:312892 # Consistently use / as path separator to simplify the writing of regex
2893 # expressions.
Sam Maiera6e76d72022-02-11 21:43:502894 file_filter = lambda f: not input_api.re.match(
Bruce Dawson40fece62022-09-16 19:58:312895 r"^third_party/blink/renderer/platform/heap/.*",
2896 f.LocalPath().replace(input_api.os_path.sep, '/'))
Sam Maiera6e76d72022-02-11 21:43:502897 errors = []
Omer Katzcc77ea92021-04-26 10:23:282898
Sam Maiera6e76d72022-02-11 21:43:502899 for f in input_api.AffectedFiles(file_filter=file_filter):
2900 for line_num, line in f.ChangedContents():
2901 if impl_pattern.match(line) or v8_wrapper_pattern.match(line):
2902 errors.append(' %s:%d' % (f.LocalPath(), line_num))
Omer Katzcc77ea92021-04-26 10:23:282903
Sam Maiera6e76d72022-02-11 21:43:502904 results = []
2905 if errors:
2906 results.append(
2907 output_api.PresubmitError(
2908 'Do not include files from third_party/blink/renderer/platform/heap/impl'
2909 ' or third_party/blink/renderer/platform/heap/v8_wrapper. Use the '
2910 'relevant counterparts from third_party/blink/renderer/platform/heap',
2911 errors))
2912 return results
Omer Katzcc77ea92021-04-26 10:23:282913
2914
[email protected]70ca77752012-11-20 03:45:032915def _CheckForVersionControlConflictsInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:502916 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2917 errors = []
2918 for line_num, line in f.ChangedContents():
2919 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
2920 # First-level headers in markdown look a lot like version control
2921 # conflict markers. http://daringfireball.net/projects/markdown/basics
2922 continue
2923 if pattern.match(line):
2924 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2925 return errors
[email protected]70ca77752012-11-20 03:45:032926
2927
Saagar Sanghavifceeaae2020-08-12 16:40:362928def CheckForVersionControlConflicts(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502929 """Usually this is not intentional and will cause a compile failure."""
2930 errors = []
2931 for f in input_api.AffectedFiles():
2932 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
[email protected]70ca77752012-11-20 03:45:032933
Sam Maiera6e76d72022-02-11 21:43:502934 results = []
2935 if errors:
2936 results.append(
2937 output_api.PresubmitError(
2938 'Version control conflict markers found, please resolve.',
2939 errors))
2940 return results
[email protected]70ca77752012-11-20 03:45:032941
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202942
Saagar Sanghavifceeaae2020-08-12 16:40:362943def CheckGoogleSupportAnswerUrlOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502944 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2945 errors = []
2946 for f in input_api.AffectedFiles():
2947 for line_num, line in f.ChangedContents():
2948 if pattern.search(line):
2949 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
estadee17314a02017-01-12 16:22:162950
Sam Maiera6e76d72022-02-11 21:43:502951 results = []
2952 if errors:
2953 results.append(
2954 output_api.PresubmitPromptWarning(
2955 'Found Google support URL addressed by answer number. Please replace '
2956 'with a p= identifier instead. See crbug.com/679462\n',
2957 errors))
2958 return results
estadee17314a02017-01-12 16:22:162959
[email protected]70ca77752012-11-20 03:45:032960
Saagar Sanghavifceeaae2020-08-12 16:40:362961def CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502962 def FilterFile(affected_file):
2963 """Filter function for use with input_api.AffectedSourceFiles,
2964 below. This filters out everything except non-test files from
2965 top-level directories that generally speaking should not hard-code
2966 service URLs (e.g. src/android_webview/, src/content/ and others).
2967 """
2968 return input_api.FilterSourceFile(
2969 affected_file,
Bruce Dawson40fece62022-09-16 19:58:312970 files_to_check=[r'^(android_webview|base|content|net)/.*'],
Sam Maiera6e76d72022-02-11 21:43:502971 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2972 input_api.DEFAULT_FILES_TO_SKIP))
[email protected]06e6d0ff2012-12-11 01:36:442973
Sam Maiera6e76d72022-02-11 21:43:502974 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2975 '\.(com|net)[^"]*"')
2976 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2977 pattern = input_api.re.compile(base_pattern)
2978 problems = [] # items are (filename, line_number, line)
2979 for f in input_api.AffectedSourceFiles(FilterFile):
2980 for line_num, line in f.ChangedContents():
2981 if not comment_pattern.search(line) and pattern.search(line):
2982 problems.append((f.LocalPath(), line_num, line))
[email protected]06e6d0ff2012-12-11 01:36:442983
Sam Maiera6e76d72022-02-11 21:43:502984 if problems:
2985 return [
2986 output_api.PresubmitPromptOrNotify(
2987 'Most layers below src/chrome/ should not hardcode service URLs.\n'
2988 'Are you sure this is correct?', [
2989 ' %s:%d: %s' % (problem[0], problem[1], problem[2])
2990 for problem in problems
2991 ])
2992 ]
2993 else:
2994 return []
[email protected]06e6d0ff2012-12-11 01:36:442995
2996
Saagar Sanghavifceeaae2020-08-12 16:40:362997def CheckChromeOsSyncedPrefRegistration(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:502998 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
James Cook6b6597c2019-11-06 22:05:292999
Sam Maiera6e76d72022-02-11 21:43:503000 def FileFilter(affected_file):
3001 """Includes directories known to be Chrome OS only."""
3002 return input_api.FilterSourceFile(
3003 affected_file,
3004 files_to_check=(
3005 '^ash/',
3006 '^chromeos/', # Top-level src/chromeos.
3007 '.*/chromeos/', # Any path component.
3008 '^components/arc',
3009 '^components/exo'),
3010 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP))
James Cook6b6597c2019-11-06 22:05:293011
Sam Maiera6e76d72022-02-11 21:43:503012 prefs = []
3013 priority_prefs = []
3014 for f in input_api.AffectedFiles(file_filter=FileFilter):
3015 for line_num, line in f.ChangedContents():
3016 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF',
3017 line):
3018 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
3019 prefs.append(' %s' % line)
3020 if input_api.re.search(
3021 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
3022 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
3023 priority_prefs.append(' %s' % line)
3024
3025 results = []
3026 if (prefs):
3027 results.append(
3028 output_api.PresubmitPromptWarning(
3029 'Preferences were registered as SYNCABLE_PREF and will be controlled '
3030 'by browser sync settings. If these prefs should be controlled by OS '
3031 'sync settings use SYNCABLE_OS_PREF instead.\n' +
3032 '\n'.join(prefs)))
3033 if (priority_prefs):
3034 results.append(
3035 output_api.PresubmitPromptWarning(
3036 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
3037 'controlled by browser sync settings. If these prefs should be '
3038 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
3039 'instead.\n' + '\n'.join(prefs)))
3040 return results
James Cook6b6597c2019-11-06 22:05:293041
3042
Saagar Sanghavifceeaae2020-08-12 16:40:363043def CheckNoAbbreviationInPngFileName(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503044 """Makes sure there are no abbreviations in the name of PNG files.
3045 The native_client_sdk directory is excluded because it has auto-generated PNG
3046 files for documentation.
3047 """
3048 errors = []
Yuanqing Zhu9eef02832022-12-04 14:42:173049 files_to_check = [r'.*\.png$']
Bruce Dawson40fece62022-09-16 19:58:313050 files_to_skip = [r'^native_client_sdk/',
3051 r'^services/test/',
3052 r'^third_party/blink/web_tests/',
Bruce Dawson3db456212022-05-02 05:34:183053 ]
Sam Maiera6e76d72022-02-11 21:43:503054 file_filter = lambda f: input_api.FilterSourceFile(
3055 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
Yuanqing Zhu9eef02832022-12-04 14:42:173056 abbreviation = input_api.re.compile('.+_[a-z]\.png|.+_[a-z]_.*\.png')
Sam Maiera6e76d72022-02-11 21:43:503057 for f in input_api.AffectedFiles(include_deletes=False,
3058 file_filter=file_filter):
Yuanqing Zhu9eef02832022-12-04 14:42:173059 file_name = input_api.os_path.split(f.LocalPath())[1]
3060 if abbreviation.search(file_name):
3061 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:273062
Sam Maiera6e76d72022-02-11 21:43:503063 results = []
3064 if errors:
3065 results.append(
3066 output_api.PresubmitError(
3067 'The name of PNG files should not have abbreviations. \n'
3068 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
3069 'Contact [email protected] if you have questions.', errors))
3070 return results
[email protected]d2530012013-01-25 16:39:273071
Evan Stade7cd4a2c2022-08-04 23:37:253072def CheckNoProductIconsAddedToPublicRepo(input_api, output_api):
3073 """Heuristically identifies product icons based on their file name and reminds
3074 contributors not to add them to the Chromium repository.
3075 """
3076 errors = []
3077 files_to_check = [r'.*google.*\.png$|.*google.*\.svg$|.*google.*\.icon$']
3078 file_filter = lambda f: input_api.FilterSourceFile(
3079 f, files_to_check=files_to_check)
3080 for f in input_api.AffectedFiles(include_deletes=False,
3081 file_filter=file_filter):
3082 errors.append(' %s' % f.LocalPath())
3083
3084 results = []
3085 if errors:
Bruce Dawson3bcf0c92022-08-12 00:03:083086 # Give warnings instead of errors on presubmit --all and presubmit
3087 # --files.
3088 message_type = (output_api.PresubmitNotifyResult if input_api.no_diffs
3089 else output_api.PresubmitError)
Evan Stade7cd4a2c2022-08-04 23:37:253090 results.append(
Bruce Dawson3bcf0c92022-08-12 00:03:083091 message_type(
Evan Stade7cd4a2c2022-08-04 23:37:253092 'Trademarked images should not be added to the public repo. '
3093 'See crbug.com/944754', errors))
3094 return results
3095
[email protected]d2530012013-01-25 16:39:273096
Daniel Cheng4dcdb6b2017-04-13 08:30:173097def _ExtractAddRulesFromParsedDeps(parsed_deps):
Sam Maiera6e76d72022-02-11 21:43:503098 """Extract the rules that add dependencies from a parsed DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:173099
Sam Maiera6e76d72022-02-11 21:43:503100 Args:
3101 parsed_deps: the locals dictionary from evaluating the DEPS file."""
3102 add_rules = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:173103 add_rules.update([
Sam Maiera6e76d72022-02-11 21:43:503104 rule[1:] for rule in parsed_deps.get('include_rules', [])
Daniel Cheng4dcdb6b2017-04-13 08:30:173105 if rule.startswith('+') or rule.startswith('!')
3106 ])
Sam Maiera6e76d72022-02-11 21:43:503107 for _, rules in parsed_deps.get('specific_include_rules', {}).items():
3108 add_rules.update([
3109 rule[1:] for rule in rules
3110 if rule.startswith('+') or rule.startswith('!')
3111 ])
3112 return add_rules
Daniel Cheng4dcdb6b2017-04-13 08:30:173113
3114
3115def _ParseDeps(contents):
Sam Maiera6e76d72022-02-11 21:43:503116 """Simple helper for parsing DEPS files."""
Daniel Cheng4dcdb6b2017-04-13 08:30:173117
Sam Maiera6e76d72022-02-11 21:43:503118 # Stubs for handling special syntax in the root DEPS file.
3119 class _VarImpl:
3120 def __init__(self, local_scope):
3121 self._local_scope = local_scope
Daniel Cheng4dcdb6b2017-04-13 08:30:173122
Sam Maiera6e76d72022-02-11 21:43:503123 def Lookup(self, var_name):
3124 """Implements the Var syntax."""
3125 try:
3126 return self._local_scope['vars'][var_name]
3127 except KeyError:
3128 raise Exception('Var is not defined: %s' % var_name)
Daniel Cheng4dcdb6b2017-04-13 08:30:173129
Sam Maiera6e76d72022-02-11 21:43:503130 local_scope = {}
3131 global_scope = {
3132 'Var': _VarImpl(local_scope).Lookup,
3133 'Str': str,
3134 }
Dirk Pranke1b9e06382021-05-14 01:16:223135
Sam Maiera6e76d72022-02-11 21:43:503136 exec(contents, global_scope, local_scope)
3137 return local_scope
Daniel Cheng4dcdb6b2017-04-13 08:30:173138
3139
3140def _CalculateAddedDeps(os_path, old_contents, new_contents):
Sam Maiera6e76d72022-02-11 21:43:503141 """Helper method for CheckAddedDepsHaveTargetApprovals. Returns
3142 a set of DEPS entries that we should look up.
[email protected]14a6131c2014-01-08 01:15:413143
Sam Maiera6e76d72022-02-11 21:43:503144 For a directory (rather than a specific filename) we fake a path to
3145 a specific filename by adding /DEPS. This is chosen as a file that
3146 will seldom or never be subject to per-file include_rules.
3147 """
3148 # We ignore deps entries on auto-generated directories.
3149 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:083150
Sam Maiera6e76d72022-02-11 21:43:503151 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
3152 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
Daniel Cheng4dcdb6b2017-04-13 08:30:173153
Sam Maiera6e76d72022-02-11 21:43:503154 added_deps = new_deps.difference(old_deps)
Daniel Cheng4dcdb6b2017-04-13 08:30:173155
Sam Maiera6e76d72022-02-11 21:43:503156 results = set()
3157 for added_dep in added_deps:
3158 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
3159 continue
3160 # Assume that a rule that ends in .h is a rule for a specific file.
3161 if added_dep.endswith('.h'):
3162 results.add(added_dep)
3163 else:
3164 results.add(os_path.join(added_dep, 'DEPS'))
3165 return results
[email protected]f32e2d1e2013-07-26 21:39:083166
3167
Saagar Sanghavifceeaae2020-08-12 16:40:363168def CheckAddedDepsHaveTargetApprovals(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503169 """When a dependency prefixed with + is added to a DEPS file, we
3170 want to make sure that the change is reviewed by an OWNER of the
3171 target file or directory, to avoid layering violations from being
3172 introduced. This check verifies that this happens.
3173 """
3174 # We rely on Gerrit's code-owners to check approvals.
3175 # input_api.gerrit is always set for Chromium, but other projects
3176 # might not use Gerrit.
Bruce Dawson344ab262022-06-04 11:35:103177 if not input_api.gerrit or input_api.no_diffs:
Sam Maiera6e76d72022-02-11 21:43:503178 return []
Bruce Dawsonb357aeb2022-08-09 15:38:303179 if 'PRESUBMIT_SKIP_NETWORK' in input_api.environ:
Sam Maiera6e76d72022-02-11 21:43:503180 return []
Bruce Dawsonb357aeb2022-08-09 15:38:303181 try:
3182 if (input_api.change.issue and
3183 input_api.gerrit.IsOwnersOverrideApproved(
3184 input_api.change.issue)):
3185 # Skip OWNERS check when Owners-Override label is approved. This is
3186 # intended for global owners, trusted bots, and on-call sheriffs.
3187 # Review is still required for these changes.
3188 return []
3189 except Exception as e:
Sam Maier4cef9242022-10-03 14:21:243190 return [output_api.PresubmitPromptWarning(
3191 'Failed to retrieve owner override status - %s' % str(e))]
Edward Lesmes6fba51082021-01-20 04:20:233192
Sam Maiera6e76d72022-02-11 21:43:503193 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:243194
Bruce Dawson40fece62022-09-16 19:58:313195 # Consistently use / as path separator to simplify the writing of regex
3196 # expressions.
Sam Maiera6e76d72022-02-11 21:43:503197 file_filter = lambda f: not input_api.re.match(
Bruce Dawson40fece62022-09-16 19:58:313198 r"^third_party/blink/.*",
3199 f.LocalPath().replace(input_api.os_path.sep, '/'))
Sam Maiera6e76d72022-02-11 21:43:503200 for f in input_api.AffectedFiles(include_deletes=False,
3201 file_filter=file_filter):
3202 filename = input_api.os_path.basename(f.LocalPath())
3203 if filename == 'DEPS':
3204 virtual_depended_on_files.update(
3205 _CalculateAddedDeps(input_api.os_path,
3206 '\n'.join(f.OldContents()),
3207 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:553208
Sam Maiera6e76d72022-02-11 21:43:503209 if not virtual_depended_on_files:
3210 return []
[email protected]e871964c2013-05-13 14:14:553211
Sam Maiera6e76d72022-02-11 21:43:503212 if input_api.is_committing:
3213 if input_api.tbr:
3214 return [
3215 output_api.PresubmitNotifyResult(
3216 '--tbr was specified, skipping OWNERS check for DEPS additions'
3217 )
3218 ]
Daniel Cheng3008dc12022-05-13 04:02:113219 # TODO(dcheng): Make this generate an error on dry runs if the reviewer
3220 # is not added, to prevent review serialization.
Sam Maiera6e76d72022-02-11 21:43:503221 if input_api.dry_run:
3222 return [
3223 output_api.PresubmitNotifyResult(
3224 'This is a dry run, skipping OWNERS check for DEPS additions'
3225 )
3226 ]
3227 if not input_api.change.issue:
3228 return [
3229 output_api.PresubmitError(
3230 "DEPS approval by OWNERS check failed: this change has "
3231 "no change number, so we can't check it for approvals.")
3232 ]
3233 output = output_api.PresubmitError
[email protected]14a6131c2014-01-08 01:15:413234 else:
Sam Maiera6e76d72022-02-11 21:43:503235 output = output_api.PresubmitNotifyResult
[email protected]e871964c2013-05-13 14:14:553236
Sam Maiera6e76d72022-02-11 21:43:503237 owner_email, reviewers = (
3238 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
3239 input_api, None, approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:553240
Sam Maiera6e76d72022-02-11 21:43:503241 owner_email = owner_email or input_api.change.author_email
3242
3243 approval_status = input_api.owners_client.GetFilesApprovalStatus(
3244 virtual_depended_on_files, reviewers.union([owner_email]), [])
3245 missing_files = [
3246 f for f in virtual_depended_on_files
3247 if approval_status[f] != input_api.owners_client.APPROVED
3248 ]
3249
3250 # We strip the /DEPS part that was added by
3251 # _FilesToCheckForIncomingDeps to fake a path to a file in a
3252 # directory.
3253 def StripDeps(path):
3254 start_deps = path.rfind('/DEPS')
3255 if start_deps != -1:
3256 return path[:start_deps]
3257 else:
3258 return path
3259
3260 unapproved_dependencies = [
3261 "'+%s'," % StripDeps(path) for path in missing_files
3262 ]
3263
3264 if unapproved_dependencies:
3265 output_list = [
3266 output(
3267 'You need LGTM from owners of depends-on paths in DEPS that were '
3268 'modified in this CL:\n %s' %
3269 '\n '.join(sorted(unapproved_dependencies)))
3270 ]
3271 suggested_owners = input_api.owners_client.SuggestOwners(
3272 missing_files, exclude=[owner_email])
3273 output_list.append(
3274 output('Suggested missing target path OWNERS:\n %s' %
3275 '\n '.join(suggested_owners or [])))
3276 return output_list
3277
3278 return []
[email protected]e871964c2013-05-13 14:14:553279
3280
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493281# TODO: add unit tests.
Saagar Sanghavifceeaae2020-08-12 16:40:363282def CheckSpamLogging(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503283 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
3284 files_to_skip = (
3285 _EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
3286 input_api.DEFAULT_FILES_TO_SKIP + (
Jaewon Jung2f323bb2022-12-07 23:55:013287 r"^base/fuchsia/scoped_fx_logger\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313288 r"^base/logging\.h$",
3289 r"^base/logging\.cc$",
3290 r"^base/task/thread_pool/task_tracker\.cc$",
3291 r"^chrome/app/chrome_main_delegate\.cc$",
Yao Li359937b2023-02-15 23:43:033292 r"^chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer\.cc$",
3293 r"^chrome/browser/ash/policy/remote_commands/user_command_arc_job\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313294 r"^chrome/browser/chrome_browser_main\.cc$",
3295 r"^chrome/browser/ui/startup/startup_browser_creator\.cc$",
3296 r"^chrome/browser/browser_switcher/bho/.*",
3297 r"^chrome/browser/diagnostics/diagnostics_writer\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313298 r"^chrome/chrome_elf/dll_hash/dll_hash_main\.cc$",
3299 r"^chrome/installer/setup/.*",
3300 r"^chromecast/",
Vigen Issahhanjane2d93822023-06-30 15:57:203301 r"^components/cast",
Bruce Dawson40fece62022-09-16 19:58:313302 r"^components/media_control/renderer/media_playback_options\.cc$",
Salma Elmahallawy52976452023-01-27 17:04:493303 r"^components/policy/core/common/policy_logger\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313304 r"^components/viz/service/display/"
Sam Maiera6e76d72022-02-11 21:43:503305 r"overlay_strategy_underlay_cast\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313306 r"^components/zucchini/.*",
Sam Maiera6e76d72022-02-11 21:43:503307 # TODO(peter): Remove exception. https://crbug.com/534537
Bruce Dawson40fece62022-09-16 19:58:313308 r"^content/browser/notifications/"
Sam Maiera6e76d72022-02-11 21:43:503309 r"notification_event_dispatcher_impl\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313310 r"^content/common/gpu/client/gl_helper_benchmark\.cc$",
3311 r"^courgette/courgette_minimal_tool\.cc$",
3312 r"^courgette/courgette_tool\.cc$",
3313 r"^extensions/renderer/logging_native_handler\.cc$",
3314 r"^fuchsia_web/common/init_logging\.cc$",
3315 r"^fuchsia_web/runners/common/web_component\.cc$",
Caroline Liua7050132023-02-13 22:23:153316 r"^fuchsia_web/shell/.*\.cc$",
Bruce Dawson40fece62022-09-16 19:58:313317 r"^headless/app/headless_shell\.cc$",
3318 r"^ipc/ipc_logging\.cc$",
3319 r"^native_client_sdk/",
3320 r"^remoting/base/logging\.h$",
3321 r"^remoting/host/.*",
3322 r"^sandbox/linux/.*",
3323 r"^storage/browser/file_system/dump_file_system\.cc$",
3324 r"^tools/",
3325 r"^ui/base/resource/data_pack\.cc$",
3326 r"^ui/aura/bench/bench_main\.cc$",
3327 r"^ui/ozone/platform/cast/",
3328 r"^ui/base/x/xwmstartupcheck/"
Sam Maiera6e76d72022-02-11 21:43:503329 r"xwmstartupcheck\.cc$"))
3330 source_file_filter = lambda x: input_api.FilterSourceFile(
3331 x, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
[email protected]85218562013-11-22 07:41:403332
Sam Maiera6e76d72022-02-11 21:43:503333 log_info = set([])
3334 printf = set([])
[email protected]85218562013-11-22 07:41:403335
Sam Maiera6e76d72022-02-11 21:43:503336 for f in input_api.AffectedSourceFiles(source_file_filter):
3337 for _, line in f.ChangedContents():
3338 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
3339 log_info.add(f.LocalPath())
3340 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
3341 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:373342
Sam Maiera6e76d72022-02-11 21:43:503343 if input_api.re.search(r"\bprintf\(", line):
3344 printf.add(f.LocalPath())
3345 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
3346 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:403347
Sam Maiera6e76d72022-02-11 21:43:503348 if log_info:
3349 return [
3350 output_api.PresubmitError(
3351 'These files spam the console log with LOG(INFO):',
3352 items=log_info)
3353 ]
3354 if printf:
3355 return [
3356 output_api.PresubmitError(
3357 'These files spam the console log with printf/fprintf:',
3358 items=printf)
3359 ]
3360 return []
[email protected]85218562013-11-22 07:41:403361
3362
Saagar Sanghavifceeaae2020-08-12 16:40:363363def CheckForAnonymousVariables(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503364 """These types are all expected to hold locks while in scope and
3365 so should never be anonymous (which causes them to be immediately
3366 destroyed)."""
3367 they_who_must_be_named = [
3368 'base::AutoLock',
3369 'base::AutoReset',
3370 'base::AutoUnlock',
3371 'SkAutoAlphaRestore',
3372 'SkAutoBitmapShaderInstall',
3373 'SkAutoBlitterChoose',
3374 'SkAutoBounderCommit',
3375 'SkAutoCallProc',
3376 'SkAutoCanvasRestore',
3377 'SkAutoCommentBlock',
3378 'SkAutoDescriptor',
3379 'SkAutoDisableDirectionCheck',
3380 'SkAutoDisableOvalCheck',
3381 'SkAutoFree',
3382 'SkAutoGlyphCache',
3383 'SkAutoHDC',
3384 'SkAutoLockColors',
3385 'SkAutoLockPixels',
3386 'SkAutoMalloc',
3387 'SkAutoMaskFreeImage',
3388 'SkAutoMutexAcquire',
3389 'SkAutoPathBoundsUpdate',
3390 'SkAutoPDFRelease',
3391 'SkAutoRasterClipValidate',
3392 'SkAutoRef',
3393 'SkAutoTime',
3394 'SkAutoTrace',
3395 'SkAutoUnref',
3396 ]
3397 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
3398 # bad: base::AutoLock(lock.get());
3399 # not bad: base::AutoLock lock(lock.get());
3400 bad_pattern = input_api.re.compile(anonymous)
3401 # good: new base::AutoLock(lock.get())
3402 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
3403 errors = []
[email protected]49aa76a2013-12-04 06:59:163404
Sam Maiera6e76d72022-02-11 21:43:503405 for f in input_api.AffectedFiles():
3406 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
3407 continue
3408 for linenum, line in f.ChangedContents():
3409 if bad_pattern.search(line) and not good_pattern.search(line):
3410 errors.append('%s:%d' % (f.LocalPath(), linenum))
[email protected]49aa76a2013-12-04 06:59:163411
Sam Maiera6e76d72022-02-11 21:43:503412 if errors:
3413 return [
3414 output_api.PresubmitError(
3415 'These lines create anonymous variables that need to be named:',
3416 items=errors)
3417 ]
3418 return []
[email protected]49aa76a2013-12-04 06:59:163419
3420
Saagar Sanghavifceeaae2020-08-12 16:40:363421def CheckUniquePtrOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503422 # Returns whether |template_str| is of the form <T, U...> for some types T
3423 # and U. Assumes that |template_str| is already in the form <...>.
3424 def HasMoreThanOneArg(template_str):
3425 # Level of <...> nesting.
3426 nesting = 0
3427 for c in template_str:
3428 if c == '<':
3429 nesting += 1
3430 elif c == '>':
3431 nesting -= 1
3432 elif c == ',' and nesting == 1:
3433 return True
3434 return False
Vaclav Brozekb7fadb692018-08-30 06:39:533435
Sam Maiera6e76d72022-02-11 21:43:503436 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
3437 sources = lambda affected_file: input_api.FilterSourceFile(
3438 affected_file,
3439 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
3440 DEFAULT_FILES_TO_SKIP),
3441 files_to_check=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:553442
Sam Maiera6e76d72022-02-11 21:43:503443 # Pattern to capture a single "<...>" block of template arguments. It can
3444 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
3445 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
3446 # latter would likely require counting that < and > match, which is not
3447 # expressible in regular languages. Should the need arise, one can introduce
3448 # limited counting (matching up to a total number of nesting depth), which
3449 # should cover all practical cases for already a low nesting limit.
3450 template_arg_pattern = (
3451 r'<[^>]*' # Opening block of <.
3452 r'>([^<]*>)?') # Closing block of >.
3453 # Prefix expressing that whatever follows is not already inside a <...>
3454 # block.
3455 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
3456 null_construct_pattern = input_api.re.compile(
3457 not_inside_template_arg_pattern + r'\bstd::unique_ptr' +
3458 template_arg_pattern + r'\(\)')
Vaclav Brozeka54c528b2018-04-06 19:23:553459
Sam Maiera6e76d72022-02-11 21:43:503460 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
3461 template_arg_no_array_pattern = (
3462 r'<[^>]*[^]]' # Opening block of <.
3463 r'>([^(<]*[^]]>)?') # Closing block of >.
3464 # Prefix saying that what follows is the start of an expression.
3465 start_of_expr_pattern = r'(=|\breturn|^)\s*'
3466 # Suffix saying that what follows are call parentheses with a non-empty list
3467 # of arguments.
3468 nonempty_arg_list_pattern = r'\(([^)]|$)'
3469 # Put the template argument into a capture group for deeper examination later.
3470 return_construct_pattern = input_api.re.compile(
3471 start_of_expr_pattern + r'std::unique_ptr' + '(?P<template_arg>' +
3472 template_arg_no_array_pattern + ')' + nonempty_arg_list_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:553473
Sam Maiera6e76d72022-02-11 21:43:503474 problems_constructor = []
3475 problems_nullptr = []
3476 for f in input_api.AffectedSourceFiles(sources):
3477 for line_number, line in f.ChangedContents():
3478 # Disallow:
3479 # return std::unique_ptr<T>(foo);
3480 # bar = std::unique_ptr<T>(foo);
3481 # But allow:
3482 # return std::unique_ptr<T[]>(foo);
3483 # bar = std::unique_ptr<T[]>(foo);
3484 # And also allow cases when the second template argument is present. Those
3485 # cases cannot be handled by std::make_unique:
3486 # return std::unique_ptr<T, U>(foo);
3487 # bar = std::unique_ptr<T, U>(foo);
3488 local_path = f.LocalPath()
3489 return_construct_result = return_construct_pattern.search(line)
3490 if return_construct_result and not HasMoreThanOneArg(
3491 return_construct_result.group('template_arg')):
3492 problems_constructor.append(
3493 '%s:%d\n %s' % (local_path, line_number, line.strip()))
3494 # Disallow:
3495 # std::unique_ptr<T>()
3496 if null_construct_pattern.search(line):
3497 problems_nullptr.append(
3498 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Vaclav Brozek851d9602018-04-04 16:13:053499
Sam Maiera6e76d72022-02-11 21:43:503500 errors = []
3501 if problems_nullptr:
3502 errors.append(
3503 output_api.PresubmitPromptWarning(
3504 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
3505 problems_nullptr))
3506 if problems_constructor:
3507 errors.append(
3508 output_api.PresubmitError(
3509 'The following files use explicit std::unique_ptr constructor. '
3510 'Use std::make_unique<T>() instead, or use base::WrapUnique if '
3511 'std::make_unique is not an option.', problems_constructor))
3512 return errors
Peter Kasting4844e46e2018-02-23 07:27:103513
3514
Saagar Sanghavifceeaae2020-08-12 16:40:363515def CheckUserActionUpdate(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:503516 """Checks if any new user action has been added."""
3517 if any('actions.xml' == input_api.os_path.basename(f)
3518 for f in input_api.LocalPaths()):
3519 # If actions.xml is already included in the changelist, the PRESUBMIT
3520 # for actions.xml will do a more complete presubmit check.
3521 return []
3522
3523 file_inclusion_pattern = [r'.*\.(cc|mm)$']
3524 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
3525 input_api.DEFAULT_FILES_TO_SKIP)
3526 file_filter = lambda f: input_api.FilterSourceFile(
3527 f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
3528
3529 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
3530 current_actions = None
3531 for f in input_api.AffectedFiles(file_filter=file_filter):
3532 for line_num, line in f.ChangedContents():
3533 match = input_api.re.search(action_re, line)
3534 if match:
3535 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
3536 # loaded only once.
3537 if not current_actions:
Bruce Dawson6cb2d4d2023-03-01 21:35:093538 with open('tools/metrics/actions/actions.xml',
3539 encoding='utf-8') as actions_f:
Sam Maiera6e76d72022-02-11 21:43:503540 current_actions = actions_f.read()
3541 # Search for the matched user action name in |current_actions|.
3542 for action_name in match.groups():
3543 action = 'name="{0}"'.format(action_name)
3544 if action not in current_actions:
3545 return [
3546 output_api.PresubmitPromptWarning(
3547 'File %s line %d: %s is missing in '
3548 'tools/metrics/actions/actions.xml. Please run '
3549 'tools/metrics/actions/extract_actions.py to update.'
3550 % (f.LocalPath(), line_num, action_name))
3551 ]
[email protected]999261d2014-03-03 20:08:083552 return []
3553
[email protected]999261d2014-03-03 20:08:083554
Daniel Cheng13ca61a882017-08-25 15:11:253555def _ImportJSONCommentEater(input_api):
Sam Maiera6e76d72022-02-11 21:43:503556 import sys
3557 sys.path = sys.path + [
3558 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
3559 'json_comment_eater')
3560 ]
3561 import json_comment_eater
3562 return json_comment_eater
Daniel Cheng13ca61a882017-08-25 15:11:253563
3564
[email protected]99171a92014-06-03 08:44:473565def _GetJSONParseError(input_api, filename, eat_comments=True):
dchenge07de812016-06-20 19:27:173566 try:
Sam Maiera6e76d72022-02-11 21:43:503567 contents = input_api.ReadFile(filename)
3568 if eat_comments:
3569 json_comment_eater = _ImportJSONCommentEater(input_api)
3570 contents = json_comment_eater.Nom(contents)
dchenge07de812016-06-20 19:27:173571
Sam Maiera6e76d72022-02-11 21:43:503572 input_api.json.loads(contents)
3573 except ValueError as e:
3574 return e
Andrew Grieve4deedb12022-02-03 21:34:503575 return None
3576
3577
Sam Maiera6e76d72022-02-11 21:43:503578def _GetIDLParseError(input_api, filename):
3579 try:
3580 contents = input_api.ReadFile(filename)
Devlin Croninf7582a12022-04-21 21:14:283581 for i, char in enumerate(contents):
Daniel Chenga37c03db2022-05-12 17:20:343582 if not char.isascii():
3583 return (
3584 'Non-ascii character "%s" (ord %d) found at offset %d.' %
3585 (char, ord(char), i))
Sam Maiera6e76d72022-02-11 21:43:503586 idl_schema = input_api.os_path.join(input_api.PresubmitLocalPath(),
3587 'tools', 'json_schema_compiler',
3588 'idl_schema.py')
3589 process = input_api.subprocess.Popen(
Bruce Dawson679fb082022-04-14 00:47:283590 [input_api.python3_executable, idl_schema],
Sam Maiera6e76d72022-02-11 21:43:503591 stdin=input_api.subprocess.PIPE,
3592 stdout=input_api.subprocess.PIPE,
3593 stderr=input_api.subprocess.PIPE,
3594 universal_newlines=True)
3595 (_, error) = process.communicate(input=contents)
3596 return error or None
3597 except ValueError as e:
3598 return e
agrievef32bcc72016-04-04 14:57:403599
agrievef32bcc72016-04-04 14:57:403600
Sam Maiera6e76d72022-02-11 21:43:503601def CheckParseErrors(input_api, output_api):
3602 """Check that IDL and JSON files do not contain syntax errors."""
3603 actions = {
3604 '.idl': _GetIDLParseError,
3605 '.json': _GetJSONParseError,
3606 }
3607 # Most JSON files are preprocessed and support comments, but these do not.
3608 json_no_comments_patterns = [
Bruce Dawson40fece62022-09-16 19:58:313609 r'^testing/',
Sam Maiera6e76d72022-02-11 21:43:503610 ]
3611 # Only run IDL checker on files in these directories.
3612 idl_included_patterns = [
Bruce Dawson40fece62022-09-16 19:58:313613 r'^chrome/common/extensions/api/',
3614 r'^extensions/common/api/',
Sam Maiera6e76d72022-02-11 21:43:503615 ]
agrievef32bcc72016-04-04 14:57:403616
Sam Maiera6e76d72022-02-11 21:43:503617 def get_action(affected_file):
3618 filename = affected_file.LocalPath()
3619 return actions.get(input_api.os_path.splitext(filename)[1])
agrievef32bcc72016-04-04 14:57:403620
Sam Maiera6e76d72022-02-11 21:43:503621 def FilterFile(affected_file):
3622 action = get_action(affected_file)
3623 if not action:
3624 return False
3625 path = affected_file.LocalPath()
agrievef32bcc72016-04-04 14:57:403626
Sam Maiera6e76d72022-02-11 21:43:503627 if _MatchesFile(input_api,
3628 _KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS, path):
3629 return False
3630
3631 if (action == _GetIDLParseError
3632 and not _MatchesFile(input_api, idl_included_patterns, path)):
3633 return False
3634 return True
3635
3636 results = []
3637 for affected_file in input_api.AffectedFiles(file_filter=FilterFile,
3638 include_deletes=False):
3639 action = get_action(affected_file)
3640 kwargs = {}
3641 if (action == _GetJSONParseError
3642 and _MatchesFile(input_api, json_no_comments_patterns,
3643 affected_file.LocalPath())):
3644 kwargs['eat_comments'] = False
3645 parse_error = action(input_api, affected_file.AbsoluteLocalPath(),
3646 **kwargs)
3647 if parse_error:
3648 results.append(
3649 output_api.PresubmitError(
3650 '%s could not be parsed: %s' %
3651 (affected_file.LocalPath(), parse_error)))
3652 return results
3653
3654
3655def CheckJavaStyle(input_api, output_api):
3656 """Runs checkstyle on changed java files and returns errors if any exist."""
3657
3658 # Return early if no java files were modified.
3659 if not any(
3660 _IsJavaFile(input_api, f.LocalPath())
3661 for f in input_api.AffectedFiles()):
3662 return []
3663
3664 import sys
3665 original_sys_path = sys.path
3666 try:
3667 sys.path = sys.path + [
3668 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
3669 'android', 'checkstyle')
3670 ]
3671 import checkstyle
3672 finally:
3673 # Restore sys.path to what it was before.
3674 sys.path = original_sys_path
3675
Andrew Grieve4f88e3ca2022-11-22 19:09:203676 return checkstyle.run_presubmit(
Sam Maiera6e76d72022-02-11 21:43:503677 input_api,
3678 output_api,
Sam Maiera6e76d72022-02-11 21:43:503679 files_to_skip=_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP)
3680
3681
3682def CheckPythonDevilInit(input_api, output_api):
3683 """Checks to make sure devil is initialized correctly in python scripts."""
3684 script_common_initialize_pattern = input_api.re.compile(
3685 r'script_common\.InitializeEnvironment\(')
3686 devil_env_config_initialize = input_api.re.compile(
3687 r'devil_env\.config\.Initialize\(')
3688
3689 errors = []
3690
3691 sources = lambda affected_file: input_api.FilterSourceFile(
3692 affected_file,
3693 files_to_skip=(_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP + (
Bruce Dawson40fece62022-09-16 19:58:313694 r'^build/android/devil_chromium\.py',
3695 r'^third_party/.*',
Sam Maiera6e76d72022-02-11 21:43:503696 )),
3697 files_to_check=[r'.*\.py$'])
3698
3699 for f in input_api.AffectedSourceFiles(sources):
3700 for line_num, line in f.ChangedContents():
3701 if (script_common_initialize_pattern.search(line)
3702 or devil_env_config_initialize.search(line)):
3703 errors.append("%s:%d" % (f.LocalPath(), line_num))
3704
3705 results = []
3706
3707 if errors:
3708 results.append(
3709 output_api.PresubmitError(
3710 'Devil initialization should always be done using '
3711 'devil_chromium.Initialize() in the chromium project, to use better '
3712 'defaults for dependencies (ex. up-to-date version of adb).',
3713 errors))
3714
3715 return results
3716
3717
3718def _MatchesFile(input_api, patterns, path):
Bruce Dawson40fece62022-09-16 19:58:313719 # Consistently use / as path separator to simplify the writing of regex
3720 # expressions.
3721 path = path.replace(input_api.os_path.sep, '/')
Sam Maiera6e76d72022-02-11 21:43:503722 for pattern in patterns:
3723 if input_api.re.search(pattern, path):
3724 return True
3725 return False
3726
3727
Daniel Chenga37c03db2022-05-12 17:20:343728def _ChangeHasSecurityReviewer(input_api, owners_file):
3729 """Returns True iff the CL has a reviewer from SECURITY_OWNERS.
Sam Maiera6e76d72022-02-11 21:43:503730
Daniel Chenga37c03db2022-05-12 17:20:343731 Args:
3732 input_api: The presubmit input API.
3733 owners_file: OWNERS file with required reviewers. Typically, this is
3734 something like ipc/SECURITY_OWNERS.
3735
3736 Note: if the presubmit is running for commit rather than for upload, this
3737 only returns True if a security reviewer has also approved the CL.
Sam Maiera6e76d72022-02-11 21:43:503738 """
Daniel Chengd88244472022-05-16 09:08:473739 # Owners-Override should bypass all additional OWNERS enforcement checks.
3740 # A CR+1 vote will still be required to land this change.
3741 if (input_api.change.issue and input_api.gerrit.IsOwnersOverrideApproved(
3742 input_api.change.issue)):
3743 return True
3744
Daniel Chenga37c03db2022-05-12 17:20:343745 owner_email, reviewers = (
3746 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
Daniel Cheng3008dc12022-05-13 04:02:113747 input_api,
3748 None,
3749 approval_needed=input_api.is_committing and not input_api.dry_run))
Sam Maiera6e76d72022-02-11 21:43:503750
Daniel Chenga37c03db2022-05-12 17:20:343751 security_owners = input_api.owners_client.ListOwners(owners_file)
3752 return any(owner in reviewers for owner in security_owners)
Sam Maiera6e76d72022-02-11 21:43:503753
Daniel Chenga37c03db2022-05-12 17:20:343754
3755@dataclass
Daniel Cheng171dad8d2022-05-21 00:40:253756class _SecurityProblemWithItems:
3757 problem: str
3758 items: Sequence[str]
3759
3760
3761@dataclass
Daniel Chenga37c03db2022-05-12 17:20:343762class _MissingSecurityOwnersResult:
Daniel Cheng171dad8d2022-05-21 00:40:253763 owners_file_problems: Sequence[_SecurityProblemWithItems]
Daniel Chenga37c03db2022-05-12 17:20:343764 has_security_sensitive_files: bool
Daniel Cheng171dad8d2022-05-21 00:40:253765 missing_reviewer_problem: Optional[_SecurityProblemWithItems]
Daniel Chenga37c03db2022-05-12 17:20:343766
3767
3768def _FindMissingSecurityOwners(input_api,
3769 output_api,
3770 file_patterns: Sequence[str],
3771 excluded_patterns: Sequence[str],
3772 required_owners_file: str,
3773 custom_rule_function: Optional[Callable] = None
3774 ) -> _MissingSecurityOwnersResult:
3775 """Find OWNERS files missing per-file rules for security-sensitive files.
3776
3777 Args:
3778 input_api: the PRESUBMIT input API object.
3779 output_api: the PRESUBMIT output API object.
3780 file_patterns: basename patterns that require a corresponding per-file
3781 security restriction.
3782 excluded_patterns: path patterns that should be exempted from
3783 requiring a security restriction.
3784 required_owners_file: path to the required OWNERS file, e.g.
3785 ipc/SECURITY_OWNERS
3786 cc_alias: If not None, email that will be CCed automatically if the
3787 change contains security-sensitive files, as determined by
3788 `file_patterns` and `excluded_patterns`.
3789 custom_rule_function: If not None, will be called with `input_api` and
3790 the current file under consideration. Returning True will add an
3791 exact match per-file rule check for the current file.
3792 """
3793
3794 # `to_check` is a mapping of an OWNERS file path to Patterns.
3795 #
3796 # Patterns is a dictionary mapping glob patterns (suitable for use in
3797 # per-file rules) to a PatternEntry.
3798 #
Sam Maiera6e76d72022-02-11 21:43:503799 # PatternEntry is a dictionary with two keys:
3800 # - 'files': the files that are matched by this pattern
3801 # - 'rules': the per-file rules needed for this pattern
Daniel Chenga37c03db2022-05-12 17:20:343802 #
Sam Maiera6e76d72022-02-11 21:43:503803 # For example, if we expect OWNERS file to contain rules for *.mojom and
3804 # *_struct_traits*.*, Patterns might look like this:
3805 # {
3806 # '*.mojom': {
3807 # 'files': ...,
3808 # 'rules': [
3809 # 'per-file *.mojom=set noparent',
3810 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
3811 # ],
3812 # },
3813 # '*_struct_traits*.*': {
3814 # 'files': ...,
3815 # 'rules': [
3816 # 'per-file *_struct_traits*.*=set noparent',
3817 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
3818 # ],
3819 # },
3820 # }
3821 to_check = {}
Daniel Chenga37c03db2022-05-12 17:20:343822 files_to_review = []
Sam Maiera6e76d72022-02-11 21:43:503823
Daniel Chenga37c03db2022-05-12 17:20:343824 def AddPatternToCheck(file, pattern):
Sam Maiera6e76d72022-02-11 21:43:503825 owners_file = input_api.os_path.join(
Daniel Chengd88244472022-05-16 09:08:473826 input_api.os_path.dirname(file.LocalPath()), 'OWNERS')
Sam Maiera6e76d72022-02-11 21:43:503827 if owners_file not in to_check:
3828 to_check[owners_file] = {}
3829 if pattern not in to_check[owners_file]:
3830 to_check[owners_file][pattern] = {
3831 'files': [],
3832 'rules': [
Daniel Chenga37c03db2022-05-12 17:20:343833 f'per-file {pattern}=set noparent',
3834 f'per-file {pattern}=file://{required_owners_file}',
Sam Maiera6e76d72022-02-11 21:43:503835 ]
3836 }
Daniel Chenged57a162022-05-25 02:56:343837 to_check[owners_file][pattern]['files'].append(file.LocalPath())
Daniel Chenga37c03db2022-05-12 17:20:343838 files_to_review.append(file.LocalPath())
Sam Maiera6e76d72022-02-11 21:43:503839
Daniel Chenga37c03db2022-05-12 17:20:343840 # Only enforce security OWNERS rules for a directory if that directory has a
3841 # file that matches `file_patterns`. For example, if a directory only
3842 # contains *.mojom files and no *_messages*.h files, the check should only
3843 # ensure that rules for *.mojom files are present.
3844 for file in input_api.AffectedFiles(include_deletes=False):
3845 file_basename = input_api.os_path.basename(file.LocalPath())
3846 if custom_rule_function is not None and custom_rule_function(
3847 input_api, file):
3848 AddPatternToCheck(file, file_basename)
3849 continue
Sam Maiera6e76d72022-02-11 21:43:503850
Daniel Chenga37c03db2022-05-12 17:20:343851 if any(
3852 input_api.fnmatch.fnmatch(file.LocalPath(), pattern)
3853 for pattern in excluded_patterns):
Sam Maiera6e76d72022-02-11 21:43:503854 continue
3855
3856 for pattern in file_patterns:
Daniel Chenga37c03db2022-05-12 17:20:343857 # Unlike `excluded_patterns`, `file_patterns` is checked only against the
3858 # file's basename.
3859 if input_api.fnmatch.fnmatch(file_basename, pattern):
3860 AddPatternToCheck(file, pattern)
Sam Maiera6e76d72022-02-11 21:43:503861 break
3862
Daniel Chenga37c03db2022-05-12 17:20:343863 has_security_sensitive_files = bool(to_check)
Daniel Cheng171dad8d2022-05-21 00:40:253864
3865 # Check if any newly added lines in OWNERS files intersect with required
3866 # per-file OWNERS lines. If so, ensure that a security reviewer is included.
3867 # This is a hack, but is needed because the OWNERS check (by design) ignores
3868 # new OWNERS entries; otherwise, a non-owner could add someone as a new
3869 # OWNER and have that newly-added OWNER self-approve their own addition.
3870 newly_covered_files = []
3871 for file in input_api.AffectedFiles(include_deletes=False):
3872 if not file.LocalPath() in to_check:
3873 continue
3874 for _, line in file.ChangedContents():
3875 for _, entry in to_check[file.LocalPath()].items():
3876 if line in entry['rules']:
3877 newly_covered_files.extend(entry['files'])
3878
3879 missing_reviewer_problems = None
3880 if newly_covered_files and not _ChangeHasSecurityReviewer(
Daniel Chenga37c03db2022-05-12 17:20:343881 input_api, required_owners_file):
Daniel Cheng171dad8d2022-05-21 00:40:253882 missing_reviewer_problems = _SecurityProblemWithItems(
3883 f'Review from an owner in {required_owners_file} is required for '
3884 'the following newly-added files:',
3885 [f'{file}' for file in sorted(set(newly_covered_files))])
Sam Maiera6e76d72022-02-11 21:43:503886
3887 # Go through the OWNERS files to check, filtering out rules that are already
3888 # present in that OWNERS file.
3889 for owners_file, patterns in to_check.items():
3890 try:
Daniel Cheng171dad8d2022-05-21 00:40:253891 lines = set(
3892 input_api.ReadFile(
3893 input_api.os_path.join(input_api.change.RepositoryRoot(),
3894 owners_file)).splitlines())
3895 for entry in patterns.values():
3896 entry['rules'] = [
3897 rule for rule in entry['rules'] if rule not in lines
3898 ]
Sam Maiera6e76d72022-02-11 21:43:503899 except IOError:
3900 # No OWNERS file, so all the rules are definitely missing.
3901 continue
3902
3903 # All the remaining lines weren't found in OWNERS files, so emit an error.
Daniel Cheng171dad8d2022-05-21 00:40:253904 owners_file_problems = []
Daniel Chenga37c03db2022-05-12 17:20:343905
Sam Maiera6e76d72022-02-11 21:43:503906 for owners_file, patterns in to_check.items():
3907 missing_lines = []
3908 files = []
3909 for _, entry in patterns.items():
Daniel Chenged57a162022-05-25 02:56:343910 files.extend(entry['files'])
Sam Maiera6e76d72022-02-11 21:43:503911 missing_lines.extend(entry['rules'])
Sam Maiera6e76d72022-02-11 21:43:503912 if missing_lines:
Daniel Cheng171dad8d2022-05-21 00:40:253913 joined_missing_lines = '\n'.join(line for line in missing_lines)
3914 owners_file_problems.append(
3915 _SecurityProblemWithItems(
3916 'Found missing OWNERS lines for security-sensitive files. '
3917 f'Please add the following lines to {owners_file}:\n'
3918 f'{joined_missing_lines}\n\nTo ensure security review for:',
3919 files))
Daniel Chenga37c03db2022-05-12 17:20:343920
Daniel Cheng171dad8d2022-05-21 00:40:253921 return _MissingSecurityOwnersResult(owners_file_problems,
Daniel Chenga37c03db2022-05-12 17:20:343922 has_security_sensitive_files,
Daniel Cheng171dad8d2022-05-21 00:40:253923 missing_reviewer_problems)
Daniel Chenga37c03db2022-05-12 17:20:343924
3925
3926def _CheckChangeForIpcSecurityOwners(input_api, output_api):
3927 # Whether or not a file affects IPC is (mostly) determined by a simple list
3928 # of filename patterns.
3929 file_patterns = [
3930 # Legacy IPC:
3931 '*_messages.cc',
3932 '*_messages*.h',
3933 '*_param_traits*.*',
3934 # Mojo IPC:
3935 '*.mojom',
3936 '*_mojom_traits*.*',
3937 '*_type_converter*.*',
3938 # Android native IPC:
3939 '*.aidl',
3940 ]
3941
Daniel Chenga37c03db2022-05-12 17:20:343942 excluded_patterns = [
Daniel Cheng518943f2022-05-12 22:15:463943 # These third_party directories do not contain IPCs, but contain files
3944 # matching the above patterns, which trigger false positives.
Daniel Chenga37c03db2022-05-12 17:20:343945 'third_party/crashpad/*',
3946 'third_party/blink/renderer/platform/bindings/*',
3947 'third_party/protobuf/benchmarks/python/*',
3948 'third_party/win_build_output/*',
Daniel Chengd88244472022-05-16 09:08:473949 # Enum-only mojoms used for web metrics, so no security review needed.
3950 'third_party/blink/public/mojom/use_counter/metrics/*',
Daniel Chenga37c03db2022-05-12 17:20:343951 # These files are just used to communicate between class loaders running
3952 # in the same process.
3953 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
3954 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
3955 ]
3956
3957 def IsMojoServiceManifestFile(input_api, file):
3958 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
3959 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
3960 if not manifest_pattern.search(file.LocalPath()):
3961 return False
3962
3963 if test_manifest_pattern.search(file.LocalPath()):
3964 return False
3965
3966 # All actual service manifest files should contain at least one
3967 # qualified reference to service_manager::Manifest.
3968 return any('service_manager::Manifest' in line
3969 for line in file.NewContents())
3970
3971 return _FindMissingSecurityOwners(
3972 input_api,
3973 output_api,
3974 file_patterns,
3975 excluded_patterns,
3976 'ipc/SECURITY_OWNERS',
3977 custom_rule_function=IsMojoServiceManifestFile)
3978
3979
3980def _CheckChangeForFuchsiaSecurityOwners(input_api, output_api):
3981 file_patterns = [
3982 # Component specifications.
3983 '*.cml', # Component Framework v2.
3984 '*.cmx', # Component Framework v1.
3985
3986 # Fuchsia IDL protocol specifications.
3987 '*.fidl',
3988 ]
3989
3990 # Don't check for owners files for changes in these directories.
3991 excluded_patterns = [
3992 'third_party/crashpad/*',
3993 ]
3994
3995 return _FindMissingSecurityOwners(input_api, output_api, file_patterns,
3996 excluded_patterns,
3997 'build/fuchsia/SECURITY_OWNERS')
3998
3999
4000def CheckSecurityOwners(input_api, output_api):
4001 """Checks that various security-sensitive files have an IPC OWNERS rule."""
4002 ipc_results = _CheckChangeForIpcSecurityOwners(input_api, output_api)
4003 fuchsia_results = _CheckChangeForFuchsiaSecurityOwners(
4004 input_api, output_api)
4005
4006 if ipc_results.has_security_sensitive_files:
4007 output_api.AppendCC('[email protected]')
Sam Maiera6e76d72022-02-11 21:43:504008
4009 results = []
Daniel Chenga37c03db2022-05-12 17:20:344010
Daniel Cheng171dad8d2022-05-21 00:40:254011 missing_reviewer_problems = []
4012 if ipc_results.missing_reviewer_problem:
4013 missing_reviewer_problems.append(ipc_results.missing_reviewer_problem)
4014 if fuchsia_results.missing_reviewer_problem:
4015 missing_reviewer_problems.append(
4016 fuchsia_results.missing_reviewer_problem)
Daniel Chenga37c03db2022-05-12 17:20:344017
Daniel Cheng171dad8d2022-05-21 00:40:254018 # Missing reviewers are an error unless there's no issue number
4019 # associated with this branch; in that case, the presubmit is being run
4020 # with --all or --files.
4021 #
4022 # Note that upload should never be an error; otherwise, it would be
4023 # impossible to upload changes at all.
4024 if input_api.is_committing and input_api.change.issue:
4025 make_presubmit_message = output_api.PresubmitError
4026 else:
4027 make_presubmit_message = output_api.PresubmitNotifyResult
4028 for problem in missing_reviewer_problems:
Sam Maiera6e76d72022-02-11 21:43:504029 results.append(
Daniel Cheng171dad8d2022-05-21 00:40:254030 make_presubmit_message(problem.problem, items=problem.items))
Daniel Chenga37c03db2022-05-12 17:20:344031
Daniel Cheng171dad8d2022-05-21 00:40:254032 owners_file_problems = []
4033 owners_file_problems.extend(ipc_results.owners_file_problems)
4034 owners_file_problems.extend(fuchsia_results.owners_file_problems)
Daniel Chenga37c03db2022-05-12 17:20:344035
Daniel Cheng171dad8d2022-05-21 00:40:254036 for problem in owners_file_problems:
Daniel Cheng3008dc12022-05-13 04:02:114037 # Missing per-file rules are always an error. While swarming and caching
4038 # means that uploading a patchset with updated OWNERS files and sending
4039 # it to the CQ again should not have a large incremental cost, it is
4040 # still frustrating to discover the error only after the change has
4041 # already been uploaded.
Daniel Chenga37c03db2022-05-12 17:20:344042 results.append(
Daniel Cheng171dad8d2022-05-21 00:40:254043 output_api.PresubmitError(problem.problem, items=problem.items))
Sam Maiera6e76d72022-02-11 21:43:504044
4045 return results
4046
4047
4048def _GetFilesUsingSecurityCriticalFunctions(input_api):
4049 """Checks affected files for changes to security-critical calls. This
4050 function checks the full change diff, to catch both additions/changes
4051 and removals.
4052
4053 Returns a dict keyed by file name, and the value is a set of detected
4054 functions.
4055 """
4056 # Map of function pretty name (displayed in an error) to the pattern to
4057 # match it with.
4058 _PATTERNS_TO_CHECK = {
4059 'content::GetServiceSandboxType<>()': 'GetServiceSandboxType\\<'
4060 }
4061 _PATTERNS_TO_CHECK = {
4062 k: input_api.re.compile(v)
4063 for k, v in _PATTERNS_TO_CHECK.items()
4064 }
4065
Sam Maiera6e76d72022-02-11 21:43:504066 # We don't want to trigger on strings within this file.
4067 def presubmit_file_filter(f):
Daniel Chenga37c03db2022-05-12 17:20:344068 return 'PRESUBMIT.py' != input_api.os_path.split(f.LocalPath())[1]
Sam Maiera6e76d72022-02-11 21:43:504069
4070 # Scan all affected files for changes touching _FUNCTIONS_TO_CHECK.
4071 files_to_functions = {}
4072 for f in input_api.AffectedFiles(file_filter=presubmit_file_filter):
4073 diff = f.GenerateScmDiff()
4074 for line in diff.split('\n'):
4075 # Not using just RightHandSideLines() because removing a
4076 # call to a security-critical function can be just as important
4077 # as adding or changing the arguments.
4078 if line.startswith('-') or (line.startswith('+')
4079 and not line.startswith('++')):
4080 for name, pattern in _PATTERNS_TO_CHECK.items():
4081 if pattern.search(line):
4082 path = f.LocalPath()
4083 if not path in files_to_functions:
4084 files_to_functions[path] = set()
4085 files_to_functions[path].add(name)
4086 return files_to_functions
4087
4088
4089def CheckSecurityChanges(input_api, output_api):
4090 """Checks that changes involving security-critical functions are reviewed
4091 by the security team.
4092 """
4093 files_to_functions = _GetFilesUsingSecurityCriticalFunctions(input_api)
4094 if not len(files_to_functions):
4095 return []
4096
Sam Maiera6e76d72022-02-11 21:43:504097 owners_file = 'ipc/SECURITY_OWNERS'
Daniel Chenga37c03db2022-05-12 17:20:344098 if _ChangeHasSecurityReviewer(input_api, owners_file):
Sam Maiera6e76d72022-02-11 21:43:504099 return []
4100
Daniel Chenga37c03db2022-05-12 17:20:344101 msg = 'The following files change calls to security-sensitive functions\n' \
Sam Maiera6e76d72022-02-11 21:43:504102 'that need to be reviewed by {}.\n'.format(owners_file)
4103 for path, names in files_to_functions.items():
4104 msg += ' {}\n'.format(path)
4105 for name in names:
4106 msg += ' {}\n'.format(name)
4107 msg += '\n'
4108
4109 if input_api.is_committing:
4110 output = output_api.PresubmitError
Mohamed Heikale217fc852020-07-06 19:44:034111 else:
Sam Maiera6e76d72022-02-11 21:43:504112 output = output_api.PresubmitNotifyResult
4113 return [output(msg)]
4114
4115
4116def CheckSetNoParent(input_api, output_api):
4117 """Checks that set noparent is only used together with an OWNERS file in
4118 //build/OWNERS.setnoparent (see also
4119 //docs/code_reviews.md#owners-files-details)
4120 """
4121 # Return early if no OWNERS files were modified.
4122 if not any(f.LocalPath().endswith('OWNERS')
4123 for f in input_api.AffectedFiles(include_deletes=False)):
4124 return []
4125
4126 errors = []
4127
4128 allowed_owners_files_file = 'build/OWNERS.setnoparent'
4129 allowed_owners_files = set()
Bruce Dawson58a45d22023-02-27 11:24:164130 with open(allowed_owners_files_file, 'r', encoding='utf-8') as f:
Sam Maiera6e76d72022-02-11 21:43:504131 for line in f:
4132 line = line.strip()
4133 if not line or line.startswith('#'):
4134 continue
4135 allowed_owners_files.add(line)
4136
4137 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
4138
4139 for f in input_api.AffectedFiles(include_deletes=False):
4140 if not f.LocalPath().endswith('OWNERS'):
4141 continue
4142
4143 found_owners_files = set()
4144 found_set_noparent_lines = dict()
4145
4146 # Parse the OWNERS file.
4147 for lineno, line in enumerate(f.NewContents(), 1):
4148 line = line.strip()
4149 if line.startswith('set noparent'):
4150 found_set_noparent_lines[''] = lineno
4151 if line.startswith('file://'):
4152 if line in allowed_owners_files:
4153 found_owners_files.add('')
4154 if line.startswith('per-file'):
4155 match = per_file_pattern.match(line)
4156 if match:
4157 glob = match.group(1).strip()
4158 directive = match.group(2).strip()
4159 if directive == 'set noparent':
4160 found_set_noparent_lines[glob] = lineno
4161 if directive.startswith('file://'):
4162 if directive in allowed_owners_files:
4163 found_owners_files.add(glob)
4164
4165 # Check that every set noparent line has a corresponding file:// line
4166 # listed in build/OWNERS.setnoparent. An exception is made for top level
4167 # directories since src/OWNERS shouldn't review them.
Bruce Dawson6bb0d672022-04-06 15:13:494168 linux_path = f.LocalPath().replace(input_api.os_path.sep, '/')
4169 if (linux_path.count('/') != 1
4170 and (not linux_path in _EXCLUDED_SET_NO_PARENT_PATHS)):
Sam Maiera6e76d72022-02-11 21:43:504171 for set_noparent_line in found_set_noparent_lines:
4172 if set_noparent_line in found_owners_files:
4173 continue
4174 errors.append(' %s:%d' %
Bruce Dawson6bb0d672022-04-06 15:13:494175 (linux_path,
Sam Maiera6e76d72022-02-11 21:43:504176 found_set_noparent_lines[set_noparent_line]))
4177
4178 results = []
4179 if errors:
4180 if input_api.is_committing:
4181 output = output_api.PresubmitError
4182 else:
4183 output = output_api.PresubmitPromptWarning
4184 results.append(
4185 output(
4186 'Found the following "set noparent" restrictions in OWNERS files that '
4187 'do not include owners from build/OWNERS.setnoparent:',
4188 long_text='\n\n'.join(errors)))
4189 return results
4190
4191
4192def CheckUselessForwardDeclarations(input_api, output_api):
4193 """Checks that added or removed lines in non third party affected
4194 header files do not lead to new useless class or struct forward
4195 declaration.
4196 """
4197 results = []
4198 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
4199 input_api.re.MULTILINE)
4200 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
4201 input_api.re.MULTILINE)
4202 for f in input_api.AffectedFiles(include_deletes=False):
4203 if (f.LocalPath().startswith('third_party')
4204 and not f.LocalPath().startswith('third_party/blink')
4205 and not f.LocalPath().startswith('third_party\\blink')):
4206 continue
4207
4208 if not f.LocalPath().endswith('.h'):
4209 continue
4210
4211 contents = input_api.ReadFile(f)
4212 fwd_decls = input_api.re.findall(class_pattern, contents)
4213 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
4214
4215 useless_fwd_decls = []
4216 for decl in fwd_decls:
4217 count = sum(1 for _ in input_api.re.finditer(
4218 r'\b%s\b' % input_api.re.escape(decl), contents))
4219 if count == 1:
4220 useless_fwd_decls.append(decl)
4221
4222 if not useless_fwd_decls:
4223 continue
4224
4225 for line in f.GenerateScmDiff().splitlines():
4226 if (line.startswith('-') and not line.startswith('--')
4227 or line.startswith('+') and not line.startswith('++')):
4228 for decl in useless_fwd_decls:
4229 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
4230 results.append(
4231 output_api.PresubmitPromptWarning(
4232 '%s: %s forward declaration is no longer needed'
4233 % (f.LocalPath(), decl)))
4234 useless_fwd_decls.remove(decl)
4235
4236 return results
4237
4238
4239def _CheckAndroidDebuggableBuild(input_api, output_api):
4240 """Checks that code uses BuildInfo.isDebugAndroid() instead of
4241 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
4242 this is a debuggable build of Android.
4243 """
4244 build_type_check_pattern = input_api.re.compile(
4245 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
4246
4247 errors = []
4248
4249 sources = lambda affected_file: input_api.FilterSourceFile(
4250 affected_file,
4251 files_to_skip=(
4252 _EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
4253 DEFAULT_FILES_TO_SKIP + (
Bruce Dawson40fece62022-09-16 19:58:314254 r"^android_webview/support_library/boundary_interfaces/",
4255 r"^chrome/android/webapk/.*",
4256 r'^third_party/.*',
4257 r"tools/android/customtabs_benchmark/.*",
4258 r"webview/chromium/License.*",
Sam Maiera6e76d72022-02-11 21:43:504259 )),
4260 files_to_check=[r'.*\.java$'])
4261
4262 for f in input_api.AffectedSourceFiles(sources):
4263 for line_num, line in f.ChangedContents():
4264 if build_type_check_pattern.search(line):
4265 errors.append("%s:%d" % (f.LocalPath(), line_num))
4266
4267 results = []
4268
4269 if errors:
4270 results.append(
4271 output_api.PresubmitPromptWarning(
4272 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
4273 ' Please use BuildInfo.isDebugAndroid() instead.', errors))
4274
4275 return results
4276
4277# TODO: add unit tests
4278def _CheckAndroidToastUsage(input_api, output_api):
4279 """Checks that code uses org.chromium.ui.widget.Toast instead of
4280 android.widget.Toast (Chromium Toast doesn't force hardware
4281 acceleration on low-end devices, saving memory).
4282 """
4283 toast_import_pattern = input_api.re.compile(
4284 r'^import android\.widget\.Toast;$')
4285
4286 errors = []
4287
4288 sources = lambda affected_file: input_api.FilterSourceFile(
4289 affected_file,
4290 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
Bruce Dawson40fece62022-09-16 19:58:314291 DEFAULT_FILES_TO_SKIP + (r'^chromecast/.*',
4292 r'^remoting/.*')),
Sam Maiera6e76d72022-02-11 21:43:504293 files_to_check=[r'.*\.java$'])
4294
4295 for f in input_api.AffectedSourceFiles(sources):
4296 for line_num, line in f.ChangedContents():
4297 if toast_import_pattern.search(line):
4298 errors.append("%s:%d" % (f.LocalPath(), line_num))
4299
4300 results = []
4301
4302 if errors:
4303 results.append(
4304 output_api.PresubmitError(
4305 'android.widget.Toast usage is detected. Android toasts use hardware'
4306 ' acceleration, and can be\ncostly on low-end devices. Please use'
4307 ' org.chromium.ui.widget.Toast instead.\n'
4308 'Contact [email protected] if you have any questions.',
4309 errors))
4310
4311 return results
4312
4313
4314def _CheckAndroidCrLogUsage(input_api, output_api):
4315 """Checks that new logs using org.chromium.base.Log:
4316 - Are using 'TAG' as variable name for the tags (warn)
4317 - Are using a tag that is shorter than 20 characters (error)
4318 """
4319
4320 # Do not check format of logs in the given files
4321 cr_log_check_excluded_paths = [
4322 # //chrome/android/webapk cannot depend on //base
Bruce Dawson40fece62022-09-16 19:58:314323 r"^chrome/android/webapk/.*",
Sam Maiera6e76d72022-02-11 21:43:504324 # WebView license viewer code cannot depend on //base; used in stub APK.
Bruce Dawson40fece62022-09-16 19:58:314325 r"^android_webview/glue/java/src/com/android/"
4326 r"webview/chromium/License.*",
Sam Maiera6e76d72022-02-11 21:43:504327 # The customtabs_benchmark is a small app that does not depend on Chromium
4328 # java pieces.
Bruce Dawson40fece62022-09-16 19:58:314329 r"tools/android/customtabs_benchmark/.*",
Sam Maiera6e76d72022-02-11 21:43:504330 ]
4331
4332 cr_log_import_pattern = input_api.re.compile(
4333 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
4334 class_in_base_pattern = input_api.re.compile(
4335 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
4336 has_some_log_import_pattern = input_api.re.compile(r'^import .*\.Log;$',
4337 input_api.re.MULTILINE)
4338 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
4339 log_call_pattern = input_api.re.compile(r'\bLog\.\w\((?P<tag>\"?\w+)')
4340 log_decl_pattern = input_api.re.compile(
4341 r'static final String TAG = "(?P<name>(.*))"')
4342 rough_log_decl_pattern = input_api.re.compile(r'\bString TAG\s*=')
4343
4344 REF_MSG = ('See docs/android_logging.md for more info.')
4345 sources = lambda x: input_api.FilterSourceFile(
4346 x,
4347 files_to_check=[r'.*\.java$'],
4348 files_to_skip=cr_log_check_excluded_paths)
4349
4350 tag_decl_errors = []
Andrew Grieved3a35d82024-01-02 21:24:384351 tag_length_errors = []
Sam Maiera6e76d72022-02-11 21:43:504352 tag_errors = []
4353 tag_with_dot_errors = []
4354 util_log_errors = []
4355
4356 for f in input_api.AffectedSourceFiles(sources):
4357 file_content = input_api.ReadFile(f)
4358 has_modified_logs = False
4359 # Per line checks
4360 if (cr_log_import_pattern.search(file_content)
4361 or (class_in_base_pattern.search(file_content)
4362 and not has_some_log_import_pattern.search(file_content))):
4363 # Checks to run for files using cr log
4364 for line_num, line in f.ChangedContents():
4365 if rough_log_decl_pattern.search(line):
4366 has_modified_logs = True
4367
4368 # Check if the new line is doing some logging
4369 match = log_call_pattern.search(line)
4370 if match:
4371 has_modified_logs = True
4372
4373 # Make sure it uses "TAG"
4374 if not match.group('tag') == 'TAG':
4375 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
4376 else:
4377 # Report non cr Log function calls in changed lines
4378 for line_num, line in f.ChangedContents():
4379 if log_call_pattern.search(line):
4380 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
4381
4382 # Per file checks
4383 if has_modified_logs:
4384 # Make sure the tag is using the "cr" prefix and is not too long
4385 match = log_decl_pattern.search(file_content)
4386 tag_name = match.group('name') if match else None
4387 if not tag_name:
4388 tag_decl_errors.append(f.LocalPath())
Andrew Grieved3a35d82024-01-02 21:24:384389 elif len(tag_name) > 20:
4390 tag_length_errors.append(f.LocalPath())
Sam Maiera6e76d72022-02-11 21:43:504391 elif '.' in tag_name:
4392 tag_with_dot_errors.append(f.LocalPath())
4393
4394 results = []
4395 if tag_decl_errors:
4396 results.append(
4397 output_api.PresubmitPromptWarning(
4398 'Please define your tags using the suggested format: .\n'
4399 '"private static final String TAG = "<package tag>".\n'
4400 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
4401 tag_decl_errors))
4402
Andrew Grieved3a35d82024-01-02 21:24:384403 if tag_length_errors:
4404 results.append(
4405 output_api.PresubmitError(
4406 'The tag length is restricted by the system to be at most '
4407 '20 characters.\n' + REF_MSG, tag_length_errors))
4408
Sam Maiera6e76d72022-02-11 21:43:504409 if tag_errors:
4410 results.append(
4411 output_api.PresubmitPromptWarning(
4412 'Please use a variable named "TAG" for your log tags.\n' +
4413 REF_MSG, tag_errors))
4414
4415 if util_log_errors:
4416 results.append(
4417 output_api.PresubmitPromptWarning(
4418 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
4419 util_log_errors))
4420
4421 if tag_with_dot_errors:
4422 results.append(
4423 output_api.PresubmitPromptWarning(
4424 'Dot in log tags cause them to be elided in crash reports.\n' +
4425 REF_MSG, tag_with_dot_errors))
4426
4427 return results
4428
4429
Sam Maiera6e76d72022-02-11 21:43:504430def _CheckAndroidTestAnnotationUsage(input_api, output_api):
4431 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
4432 deprecated_annotation_import_pattern = input_api.re.compile(
4433 r'^import android\.test\.suitebuilder\.annotation\..*;',
4434 input_api.re.MULTILINE)
4435 sources = lambda x: input_api.FilterSourceFile(
4436 x, files_to_check=[r'.*\.java$'], files_to_skip=None)
4437 errors = []
4438 for f in input_api.AffectedFiles(file_filter=sources):
4439 for line_num, line in f.ChangedContents():
4440 if deprecated_annotation_import_pattern.search(line):
4441 errors.append("%s:%d" % (f.LocalPath(), line_num))
4442
4443 results = []
4444 if errors:
4445 results.append(
4446 output_api.PresubmitError(
4447 'Annotations in android.test.suitebuilder.annotation have been'
Mohamed Heikal3d7a94c2023-03-28 16:55:244448 ' deprecated since API level 24. Please use androidx.test.filters'
4449 ' from //third_party/androidx:androidx_test_runner_java instead.'
Sam Maiera6e76d72022-02-11 21:43:504450 ' Contact [email protected] if you have any questions.',
4451 errors))
4452 return results
4453
4454
4455def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
4456 """Checks if MDPI assets are placed in a correct directory."""
Bruce Dawson6c05e852022-07-21 15:48:514457 file_filter = lambda f: (f.LocalPath().endswith(
4458 '.png') and ('/res/drawable/'.replace('/', input_api.os_path.sep) in f.
4459 LocalPath() or '/res/drawable-ldrtl/'.replace(
4460 '/', input_api.os_path.sep) in f.LocalPath()))
Sam Maiera6e76d72022-02-11 21:43:504461 errors = []
4462 for f in input_api.AffectedFiles(include_deletes=False,
4463 file_filter=file_filter):
4464 errors.append(' %s' % f.LocalPath())
4465
4466 results = []
4467 if errors:
4468 results.append(
4469 output_api.PresubmitError(
4470 'MDPI assets should be placed in /res/drawable-mdpi/ or '
4471 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
4472 '/res/drawable-ldrtl/.\n'
4473 'Contact [email protected] if you have questions.', errors))
4474 return results
4475
4476
4477def _CheckAndroidWebkitImports(input_api, output_api):
4478 """Checks that code uses org.chromium.base.Callback instead of
4479 android.webview.ValueCallback except in the WebView glue layer
4480 and WebLayer.
4481 """
4482 valuecallback_import_pattern = input_api.re.compile(
4483 r'^import android\.webkit\.ValueCallback;$')
4484
4485 errors = []
4486
4487 sources = lambda affected_file: input_api.FilterSourceFile(
4488 affected_file,
4489 files_to_skip=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.
4490 DEFAULT_FILES_TO_SKIP + (
Bruce Dawson40fece62022-09-16 19:58:314491 r'^android_webview/glue/.*',
4492 r'^weblayer/.*',
Sam Maiera6e76d72022-02-11 21:43:504493 )),
4494 files_to_check=[r'.*\.java$'])
4495
4496 for f in input_api.AffectedSourceFiles(sources):
4497 for line_num, line in f.ChangedContents():
4498 if valuecallback_import_pattern.search(line):
4499 errors.append("%s:%d" % (f.LocalPath(), line_num))
4500
4501 results = []
4502
4503 if errors:
4504 results.append(
4505 output_api.PresubmitError(
4506 'android.webkit.ValueCallback usage is detected outside of the glue'
4507 ' layer. To stay compatible with the support library, android.webkit.*'
4508 ' classes should only be used inside the glue layer and'
4509 ' org.chromium.base.Callback should be used instead.', errors))
4510
4511 return results
4512
4513
4514def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
4515 """Checks Android XML styles """
4516
4517 # Return early if no relevant files were modified.
4518 if not any(
4519 _IsXmlOrGrdFile(input_api, f.LocalPath())
4520 for f in input_api.AffectedFiles(include_deletes=False)):
4521 return []
4522
4523 import sys
4524 original_sys_path = sys.path
4525 try:
4526 sys.path = sys.path + [
4527 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
4528 'android', 'checkxmlstyle')
4529 ]
4530 import checkxmlstyle
4531 finally:
4532 # Restore sys.path to what it was before.
4533 sys.path = original_sys_path
4534
4535 if is_check_on_upload:
4536 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
4537 else:
4538 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
4539
4540
4541def _CheckAndroidInfoBarDeprecation(input_api, output_api):
4542 """Checks Android Infobar Deprecation """
4543
4544 import sys
4545 original_sys_path = sys.path
4546 try:
4547 sys.path = sys.path + [
4548 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
4549 'android', 'infobar_deprecation')
4550 ]
4551 import infobar_deprecation
4552 finally:
4553 # Restore sys.path to what it was before.
4554 sys.path = original_sys_path
4555
4556 return infobar_deprecation.CheckDeprecationOnUpload(input_api, output_api)
4557
4558
4559class _PydepsCheckerResult:
4560 def __init__(self, cmd, pydeps_path, process, old_contents):
4561 self._cmd = cmd
4562 self._pydeps_path = pydeps_path
4563 self._process = process
4564 self._old_contents = old_contents
4565
4566 def GetError(self):
4567 """Returns an error message, or None."""
4568 import difflib
Andrew Grieved27620b62023-07-13 16:35:074569 new_contents = self._process.stdout.read().splitlines()[2:]
Sam Maiera6e76d72022-02-11 21:43:504570 if self._process.wait() != 0:
4571 # STDERR should already be printed.
4572 return 'Command failed: ' + self._cmd
Sam Maiera6e76d72022-02-11 21:43:504573 if self._old_contents != new_contents:
4574 diff = '\n'.join(
4575 difflib.context_diff(self._old_contents, new_contents))
4576 return ('File is stale: {}\n'
4577 'Diff (apply to fix):\n'
4578 '{}\n'
4579 'To regenerate, run:\n\n'
4580 ' {}').format(self._pydeps_path, diff, self._cmd)
4581 return None
4582
4583
4584class PydepsChecker:
4585 def __init__(self, input_api, pydeps_files):
4586 self._file_cache = {}
4587 self._input_api = input_api
4588 self._pydeps_files = pydeps_files
4589
4590 def _LoadFile(self, path):
4591 """Returns the list of paths within a .pydeps file relative to //."""
4592 if path not in self._file_cache:
4593 with open(path, encoding='utf-8') as f:
4594 self._file_cache[path] = f.read()
4595 return self._file_cache[path]
4596
4597 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
Gao Shenga79ebd42022-08-08 17:25:594598 """Returns an iterable of paths within the .pydep, relativized to //."""
Sam Maiera6e76d72022-02-11 21:43:504599 pydeps_data = self._LoadFile(pydeps_path)
4600 uses_gn_paths = '--gn-paths' in pydeps_data
4601 entries = (l for l in pydeps_data.splitlines()
4602 if not l.startswith('#'))
4603 if uses_gn_paths:
4604 # Paths look like: //foo/bar/baz
4605 return (e[2:] for e in entries)
4606 else:
4607 # Paths look like: path/relative/to/file.pydeps
4608 os_path = self._input_api.os_path
4609 pydeps_dir = os_path.dirname(pydeps_path)
4610 return (os_path.normpath(os_path.join(pydeps_dir, e))
4611 for e in entries)
4612
4613 def _CreateFilesToPydepsMap(self):
4614 """Returns a map of local_path -> list_of_pydeps."""
4615 ret = {}
4616 for pydep_local_path in self._pydeps_files:
4617 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
4618 ret.setdefault(path, []).append(pydep_local_path)
4619 return ret
4620
4621 def ComputeAffectedPydeps(self):
4622 """Returns an iterable of .pydeps files that might need regenerating."""
4623 affected_pydeps = set()
4624 file_to_pydeps_map = None
4625 for f in self._input_api.AffectedFiles(include_deletes=True):
4626 local_path = f.LocalPath()
4627 # Changes to DEPS can lead to .pydeps changes if any .py files are in
4628 # subrepositories. We can't figure out which files change, so re-check
4629 # all files.
4630 # Changes to print_python_deps.py affect all .pydeps.
4631 if local_path in ('DEPS', 'PRESUBMIT.py'
4632 ) or local_path.endswith('print_python_deps.py'):
4633 return self._pydeps_files
4634 elif local_path.endswith('.pydeps'):
4635 if local_path in self._pydeps_files:
4636 affected_pydeps.add(local_path)
4637 elif local_path.endswith('.py'):
4638 if file_to_pydeps_map is None:
4639 file_to_pydeps_map = self._CreateFilesToPydepsMap()
4640 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
4641 return affected_pydeps
4642
4643 def DetermineIfStaleAsync(self, pydeps_path):
4644 """Runs print_python_deps.py to see if the files is stale."""
4645 import os
4646
4647 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
4648 if old_pydeps_data:
4649 cmd = old_pydeps_data[1][1:].strip()
4650 if '--output' not in cmd:
4651 cmd += ' --output ' + pydeps_path
4652 old_contents = old_pydeps_data[2:]
4653 else:
4654 # A default cmd that should work in most cases (as long as pydeps filename
4655 # matches the script name) so that PRESUBMIT.py does not crash if pydeps
4656 # file is empty/new.
4657 cmd = 'build/print_python_deps.py {} --root={} --output={}'.format(
4658 pydeps_path[:-4], os.path.dirname(pydeps_path), pydeps_path)
4659 old_contents = []
4660 env = dict(os.environ)
4661 env['PYTHONDONTWRITEBYTECODE'] = '1'
4662 process = self._input_api.subprocess.Popen(
4663 cmd + ' --output ""',
4664 shell=True,
4665 env=env,
4666 stdout=self._input_api.subprocess.PIPE,
4667 encoding='utf-8')
4668 return _PydepsCheckerResult(cmd, pydeps_path, process, old_contents)
agrievef32bcc72016-04-04 14:57:404669
4670
Tibor Goldschwendt360793f72019-06-25 18:23:494671def _ParseGclientArgs():
Sam Maiera6e76d72022-02-11 21:43:504672 args = {}
4673 with open('build/config/gclient_args.gni', 'r') as f:
4674 for line in f:
4675 line = line.strip()
4676 if not line or line.startswith('#'):
4677 continue
4678 attribute, value = line.split('=')
4679 args[attribute.strip()] = value.strip()
4680 return args
Tibor Goldschwendt360793f72019-06-25 18:23:494681
4682
Saagar Sanghavifceeaae2020-08-12 16:40:364683def CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
Sam Maiera6e76d72022-02-11 21:43:504684 """Checks if a .pydeps file needs to be regenerated."""
4685 # This check is for Python dependency lists (.pydeps files), and involves
4686 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
4687 # doesn't work on Windows and Mac, so skip it on other platforms.
4688 if not input_api.platform.startswith('linux'):
4689 return []
Erik Staabc734cd7a2021-11-23 03:11:524690
Sam Maiera6e76d72022-02-11 21:43:504691 results = []
4692 # First, check for new / deleted .pydeps.
4693 for f in input_api.AffectedFiles(include_deletes=True):
4694 # Check whether we are running the presubmit check for a file in src.
4695 # f.LocalPath is relative to repo (src, or internal repo).
4696 # os_path.exists is relative to src repo.
4697 # Therefore if os_path.exists is true, it means f.LocalPath is relative
4698 # to src and we can conclude that the pydeps is in src.
4699 if f.LocalPath().endswith('.pydeps'):
4700 if input_api.os_path.exists(f.LocalPath()):
4701 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
4702 results.append(
4703 output_api.PresubmitError(
4704 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
4705 'remove %s' % f.LocalPath()))
4706 elif f.Action() != 'D' and f.LocalPath(
4707 ) not in _ALL_PYDEPS_FILES:
4708 results.append(
4709 output_api.PresubmitError(
4710 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
4711 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:404712
Sam Maiera6e76d72022-02-11 21:43:504713 if results:
4714 return results
4715
4716 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
4717 checker = checker_for_tests or PydepsChecker(input_api, _ALL_PYDEPS_FILES)
4718 affected_pydeps = set(checker.ComputeAffectedPydeps())
4719 affected_android_pydeps = affected_pydeps.intersection(
4720 set(_ANDROID_SPECIFIC_PYDEPS_FILES))
4721 if affected_android_pydeps and not is_android:
4722 results.append(
4723 output_api.PresubmitPromptOrNotify(
4724 'You have changed python files that may affect pydeps for android\n'
Gao Shenga79ebd42022-08-08 17:25:594725 'specific scripts. However, the relevant presubmit check cannot be\n'
Sam Maiera6e76d72022-02-11 21:43:504726 'run because you are not using an Android checkout. To validate that\n'
4727 'the .pydeps are correct, re-run presubmit in an Android checkout, or\n'
4728 'use the android-internal-presubmit optional trybot.\n'
4729 'Possibly stale pydeps files:\n{}'.format(
4730 '\n'.join(affected_android_pydeps))))
4731
4732 all_pydeps = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
4733 pydeps_to_check = affected_pydeps.intersection(all_pydeps)
4734 # Process these concurrently, as each one takes 1-2 seconds.
4735 pydep_results = [checker.DetermineIfStaleAsync(p) for p in pydeps_to_check]
4736 for result in pydep_results:
4737 error_msg = result.GetError()
4738 if error_msg:
4739 results.append(output_api.PresubmitError(error_msg))
4740
agrievef32bcc72016-04-04 14:57:404741 return results
4742
agrievef32bcc72016-04-04 14:57:404743
Saagar Sanghavifceeaae2020-08-12 16:40:364744def CheckSingletonInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:504745 """Checks to make sure no header files have |Singleton<|."""
4746
4747 def FileFilter(affected_file):
4748 # It's ok for base/memory/singleton.h to have |Singleton<|.
4749 files_to_skip = (_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP +
Bruce Dawson40fece62022-09-16 19:58:314750 (r"^base/memory/singleton\.h$",
4751 r"^net/quic/platform/impl/quic_singleton_impl\.h$"))
Sam Maiera6e76d72022-02-11 21:43:504752 return input_api.FilterSourceFile(affected_file,
4753 files_to_skip=files_to_skip)
glidere61efad2015-02-18 17:39:434754
Sam Maiera6e76d72022-02-11 21:43:504755 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
4756 files = []
4757 for f in input_api.AffectedSourceFiles(FileFilter):
4758 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx')
4759 or f.LocalPath().endswith('.hpp')
4760 or f.LocalPath().endswith('.inl')):
4761 contents = input_api.ReadFile(f)
4762 for line in contents.splitlines(False):
4763 if (not line.lstrip().startswith('//')
4764 and # Strip C++ comment.
4765 pattern.search(line)):
4766 files.append(f)
4767 break
glidere61efad2015-02-18 17:39:434768
Sam Maiera6e76d72022-02-11 21:43:504769 if files:
4770 return [
4771 output_api.PresubmitError(
4772 'Found base::Singleton<T> in the following header files.\n' +
4773 'Please move them to an appropriate source file so that the ' +
4774 'template gets instantiated in a single compilation unit.',
4775 files)
4776 ]
4777 return []
glidere61efad2015-02-18 17:39:434778
4779
[email protected]fd20b902014-05-09 02:14:534780_DEPRECATED_CSS = [
4781 # Values
4782 ( "-webkit-box", "flex" ),
4783 ( "-webkit-inline-box", "inline-flex" ),
4784 ( "-webkit-flex", "flex" ),
4785 ( "-webkit-inline-flex", "inline-flex" ),
4786 ( "-webkit-min-content", "min-content" ),
4787 ( "-webkit-max-content", "max-content" ),
4788
4789 # Properties
4790 ( "-webkit-background-clip", "background-clip" ),
4791 ( "-webkit-background-origin", "background-origin" ),
4792 ( "-webkit-background-size", "background-size" ),
4793 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:444794 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:534795
4796 # Functions
4797 ( "-webkit-gradient", "gradient" ),
4798 ( "-webkit-repeating-gradient", "repeating-gradient" ),
4799 ( "-webkit-linear-gradient", "linear-gradient" ),
4800 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
4801 ( "-webkit-radial-gradient", "radial-gradient" ),
4802 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
4803]
4804
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:204805
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:494806# TODO: add unit tests
Saagar Sanghavifceeaae2020-08-12 16:40:364807def CheckNoDeprecatedCss(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:504808 """ Make sure that we don't use deprecated CSS
4809 properties, functions or values. Our external
4810 documentation and iOS CSS for dom distiller
4811 (reader mode) are ignored by the hooks as it
4812 needs to be consumed by WebKit. """
4813 results = []
4814 file_inclusion_pattern = [r".+\.css$"]
4815 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
4816 input_api.DEFAULT_FILES_TO_SKIP +
4817 (r"^chrome/common/extensions/docs", r"^chrome/docs",
4818 r"^native_client_sdk"))
4819 file_filter = lambda f: input_api.FilterSourceFile(
4820 f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
4821 for fpath in input_api.AffectedFiles(file_filter=file_filter):
4822 for line_num, line in fpath.ChangedContents():
4823 for (deprecated_value, value) in _DEPRECATED_CSS:
4824 if deprecated_value in line:
4825 results.append(
4826 output_api.PresubmitError(
4827 "%s:%d: Use of deprecated CSS %s, use %s instead" %
4828 (fpath.LocalPath(), line_num, deprecated_value,
4829 value)))
4830 return results
[email protected]fd20b902014-05-09 02:14:534831
mohan.reddyf21db962014-10-16 12:26:474832
Saagar Sanghavifceeaae2020-08-12 16:40:364833def CheckForRelativeIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:504834 bad_files = {}
4835 for f in input_api.AffectedFiles(include_deletes=False):
4836 if (f.LocalPath().startswith('third_party')
4837 and not f.LocalPath().startswith('third_party/blink')
4838 and not f.LocalPath().startswith('third_party\\blink')):
4839 continue
rlanday6802cf632017-05-30 17:48:364840
Sam Maiera6e76d72022-02-11 21:43:504841 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
4842 continue
rlanday6802cf632017-05-30 17:48:364843
Sam Maiera6e76d72022-02-11 21:43:504844 relative_includes = [
4845 line for _, line in f.ChangedContents()
4846 if "#include" in line and "../" in line
4847 ]
4848 if not relative_includes:
4849 continue
4850 bad_files[f.LocalPath()] = relative_includes
rlanday6802cf632017-05-30 17:48:364851
Sam Maiera6e76d72022-02-11 21:43:504852 if not bad_files:
4853 return []
rlanday6802cf632017-05-30 17:48:364854
Sam Maiera6e76d72022-02-11 21:43:504855 error_descriptions = []
4856 for file_path, bad_lines in bad_files.items():
4857 error_description = file_path
4858 for line in bad_lines:
4859 error_description += '\n ' + line
4860 error_descriptions.append(error_description)
rlanday6802cf632017-05-30 17:48:364861
Sam Maiera6e76d72022-02-11 21:43:504862 results = []
4863 results.append(
4864 output_api.PresubmitError(
4865 'You added one or more relative #include paths (including "../").\n'
4866 'These shouldn\'t be used because they can be used to include headers\n'
4867 'from code that\'s not correctly specified as a dependency in the\n'
4868 'relevant BUILD.gn file(s).', error_descriptions))
rlanday6802cf632017-05-30 17:48:364869
Sam Maiera6e76d72022-02-11 21:43:504870 return results
rlanday6802cf632017-05-30 17:48:364871
Takeshi Yoshinoe387aa32017-08-02 13:16:134872
Saagar Sanghavifceeaae2020-08-12 16:40:364873def CheckForCcIncludes(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:504874 """Check that nobody tries to include a cc file. It's a relatively
4875 common error which results in duplicate symbols in object
4876 files. This may not always break the build until someone later gets
4877 very confusing linking errors."""
4878 results = []
4879 for f in input_api.AffectedFiles(include_deletes=False):
4880 # We let third_party code do whatever it wants
4881 if (f.LocalPath().startswith('third_party')
4882 and not f.LocalPath().startswith('third_party/blink')
4883 and not f.LocalPath().startswith('third_party\\blink')):
4884 continue
Daniel Bratell65b033262019-04-23 08:17:064885
Sam Maiera6e76d72022-02-11 21:43:504886 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
4887 continue
Daniel Bratell65b033262019-04-23 08:17:064888
Sam Maiera6e76d72022-02-11 21:43:504889 for _, line in f.ChangedContents():
4890 if line.startswith('#include "'):
4891 included_file = line.split('"')[1]
4892 if _IsCPlusPlusFile(input_api, included_file):
4893 # The most common naming for external files with C++ code,
4894 # apart from standard headers, is to call them foo.inc, but
4895 # Chromium sometimes uses foo-inc.cc so allow that as well.
4896 if not included_file.endswith(('.h', '-inc.cc')):
4897 results.append(
4898 output_api.PresubmitError(
4899 'Only header files or .inc files should be included in other\n'
4900 'C++ files. Compiling the contents of a cc file more than once\n'
4901 'will cause duplicate information in the build which may later\n'
4902 'result in strange link_errors.\n' +
4903 f.LocalPath() + ':\n ' + line))
Daniel Bratell65b033262019-04-23 08:17:064904
Sam Maiera6e76d72022-02-11 21:43:504905 return results
Daniel Bratell65b033262019-04-23 08:17:064906
4907
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204908def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
Sam Maiera6e76d72022-02-11 21:43:504909 if not isinstance(key, ast.Str):
4910 return 'Key at line %d must be a string literal' % key.lineno
4911 if not isinstance(value, ast.Dict):
4912 return 'Value at line %d must be a dict' % value.lineno
4913 if len(value.keys) != 1:
4914 return 'Dict at line %d must have single entry' % value.lineno
4915 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
4916 return (
4917 'Entry at line %d must have a string literal \'filepath\' as key' %
4918 value.lineno)
4919 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:134920
Takeshi Yoshinoe387aa32017-08-02 13:16:134921
Sergey Ulanov4af16052018-11-08 02:41:464922def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Sam Maiera6e76d72022-02-11 21:43:504923 if not isinstance(key, ast.Str):
4924 return 'Key at line %d must be a string literal' % key.lineno
4925 if not isinstance(value, ast.List):
4926 return 'Value at line %d must be a list' % value.lineno
4927 for element in value.elts:
4928 if not isinstance(element, ast.Str):
4929 return 'Watchlist elements on line %d is not a string' % key.lineno
4930 if not email_regex.match(element.s):
4931 return ('Watchlist element on line %d doesn\'t look like a valid '
4932 + 'email: %s') % (key.lineno, element.s)
4933 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:134934
Takeshi Yoshinoe387aa32017-08-02 13:16:134935
Sergey Ulanov4af16052018-11-08 02:41:464936def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Sam Maiera6e76d72022-02-11 21:43:504937 mismatch_template = (
4938 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
4939 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:134940
Sam Maiera6e76d72022-02-11 21:43:504941 email_regex = input_api.re.compile(
4942 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
Sergey Ulanov4af16052018-11-08 02:41:464943
Sam Maiera6e76d72022-02-11 21:43:504944 ast = input_api.ast
4945 i = 0
4946 last_key = ''
4947 while True:
4948 if i >= len(wd_dict.keys):
4949 if i >= len(w_dict.keys):
4950 return None
4951 return mismatch_template % ('missing',
4952 'line %d' % w_dict.keys[i].lineno)
4953 elif i >= len(w_dict.keys):
4954 return (mismatch_template %
4955 ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:134956
Sam Maiera6e76d72022-02-11 21:43:504957 wd_key = wd_dict.keys[i]
4958 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:134959
Sam Maiera6e76d72022-02-11 21:43:504960 result = _CheckWatchlistDefinitionsEntrySyntax(wd_key,
4961 wd_dict.values[i], ast)
4962 if result is not None:
4963 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:134964
Sam Maiera6e76d72022-02-11 21:43:504965 result = _CheckWatchlistsEntrySyntax(w_key, w_dict.values[i], ast,
4966 email_regex)
4967 if result is not None:
4968 return 'Bad entry in WATCHLISTS dict: %s' % result
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204969
Sam Maiera6e76d72022-02-11 21:43:504970 if wd_key.s != w_key.s:
4971 return mismatch_template % ('%s at line %d' %
4972 (wd_key.s, wd_key.lineno),
4973 '%s at line %d' %
4974 (w_key.s, w_key.lineno))
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204975
Sam Maiera6e76d72022-02-11 21:43:504976 if wd_key.s < last_key:
4977 return (
4978 'WATCHLISTS dict is not sorted lexicographically at line %d and %d'
4979 % (wd_key.lineno, w_key.lineno))
4980 last_key = wd_key.s
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204981
Sam Maiera6e76d72022-02-11 21:43:504982 i = i + 1
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204983
4984
Sergey Ulanov4af16052018-11-08 02:41:464985def _CheckWATCHLISTSSyntax(expression, input_api):
Sam Maiera6e76d72022-02-11 21:43:504986 ast = input_api.ast
4987 if not isinstance(expression, ast.Expression):
4988 return 'WATCHLISTS file must contain a valid expression'
4989 dictionary = expression.body
4990 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
4991 return 'WATCHLISTS file must have single dict with exactly two entries'
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204992
Sam Maiera6e76d72022-02-11 21:43:504993 first_key = dictionary.keys[0]
4994 first_value = dictionary.values[0]
4995 second_key = dictionary.keys[1]
4996 second_value = dictionary.values[1]
Takeshi Yoshino3a8f9cb52017-08-10 11:32:204997
Sam Maiera6e76d72022-02-11 21:43:504998 if (not isinstance(first_key, ast.Str)
4999 or first_key.s != 'WATCHLIST_DEFINITIONS'
5000 or not isinstance(first_value, ast.Dict)):
5001 return ('The first entry of the dict in WATCHLISTS file must be '
5002 'WATCHLIST_DEFINITIONS dict')
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205003
Sam Maiera6e76d72022-02-11 21:43:505004 if (not isinstance(second_key, ast.Str) or second_key.s != 'WATCHLISTS'
5005 or not isinstance(second_value, ast.Dict)):
5006 return ('The second entry of the dict in WATCHLISTS file must be '
5007 'WATCHLISTS dict')
Takeshi Yoshino3a8f9cb52017-08-10 11:32:205008
Sam Maiera6e76d72022-02-11 21:43:505009 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:135010
5011
Saagar Sanghavifceeaae2020-08-12 16:40:365012def CheckWATCHLISTS(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505013 for f in input_api.AffectedFiles(include_deletes=False):
5014 if f.LocalPath() == 'WATCHLISTS':
5015 contents = input_api.ReadFile(f, 'r')
Takeshi Yoshinoe387aa32017-08-02 13:16:135016
Sam Maiera6e76d72022-02-11 21:43:505017 try:
5018 # First, make sure that it can be evaluated.
5019 input_api.ast.literal_eval(contents)
5020 # Get an AST tree for it and scan the tree for detailed style checking.
5021 expression = input_api.ast.parse(contents,
5022 filename='WATCHLISTS',
5023 mode='eval')
5024 except ValueError as e:
5025 return [
5026 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5027 long_text=repr(e))
5028 ]
5029 except SyntaxError as e:
5030 return [
5031 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5032 long_text=repr(e))
5033 ]
5034 except TypeError as e:
5035 return [
5036 output_api.PresubmitError('Cannot parse WATCHLISTS file',
5037 long_text=repr(e))
5038 ]
Takeshi Yoshinoe387aa32017-08-02 13:16:135039
Sam Maiera6e76d72022-02-11 21:43:505040 result = _CheckWATCHLISTSSyntax(expression, input_api)
5041 if result is not None:
5042 return [output_api.PresubmitError(result)]
5043 break
Takeshi Yoshinoe387aa32017-08-02 13:16:135044
Sam Maiera6e76d72022-02-11 21:43:505045 return []
Takeshi Yoshinoe387aa32017-08-02 13:16:135046
Sean Kaucb7c9b32022-10-25 21:25:525047def CheckGnRebasePath(input_api, output_api):
5048 """Checks that target_gen_dir is not used wtih "//" in rebase_path().
5049
5050 Developers should use root_build_dir instead of "//" when using target_gen_dir because
5051 Chromium is sometimes built outside of the source tree.
5052 """
5053
5054 def gn_files(f):
5055 return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn', ))
5056
5057 rebase_path_regex = input_api.re.compile(r'rebase_path\(("\$target_gen_dir"|target_gen_dir), ("/"|"//")\)')
5058 problems = []
5059 for f in input_api.AffectedSourceFiles(gn_files):
5060 for line_num, line in f.ChangedContents():
5061 if rebase_path_regex.search(line):
5062 problems.append(
5063 'Absolute path in rebase_path() in %s:%d' %
5064 (f.LocalPath(), line_num))
5065
5066 if problems:
5067 return [
5068 output_api.PresubmitPromptWarning(
5069 'Using an absolute path in rebase_path()',
5070 items=sorted(problems),
5071 long_text=(
5072 'rebase_path() should use root_build_dir instead of "/" ',
5073 'since builds can be initiated from outside of the source ',
5074 'root.'))
5075 ]
5076 return []
Takeshi Yoshinoe387aa32017-08-02 13:16:135077
Andrew Grieve1b290e4a22020-11-24 20:07:015078def CheckGnGlobForward(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505079 """Checks that forward_variables_from(invoker, "*") follows best practices.
Andrew Grieve1b290e4a22020-11-24 20:07:015080
Sam Maiera6e76d72022-02-11 21:43:505081 As documented at //build/docs/writing_gn_templates.md
5082 """
Andrew Grieve1b290e4a22020-11-24 20:07:015083
Sam Maiera6e76d72022-02-11 21:43:505084 def gn_files(f):
5085 return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gni', ))
Andrew Grieve1b290e4a22020-11-24 20:07:015086
Sam Maiera6e76d72022-02-11 21:43:505087 problems = []
5088 for f in input_api.AffectedSourceFiles(gn_files):
5089 for line_num, line in f.ChangedContents():
5090 if 'forward_variables_from(invoker, "*")' in line:
5091 problems.append(
5092 'Bare forward_variables_from(invoker, "*") in %s:%d' %
5093 (f.LocalPath(), line_num))
5094
5095 if problems:
5096 return [
5097 output_api.PresubmitPromptWarning(
5098 'forward_variables_from("*") without exclusions',
5099 items=sorted(problems),
5100 long_text=(
Gao Shenga79ebd42022-08-08 17:25:595101 'The variables "visibility" and "test_only" should be '
Sam Maiera6e76d72022-02-11 21:43:505102 'explicitly listed in forward_variables_from(). For more '
5103 'details, see:\n'
5104 'https://chromium.googlesource.com/chromium/src/+/HEAD/'
5105 'build/docs/writing_gn_templates.md'
5106 '#Using-forward_variables_from'))
5107 ]
5108 return []
Andrew Grieve1b290e4a22020-11-24 20:07:015109
Saagar Sanghavifceeaae2020-08-12 16:40:365110def CheckNewHeaderWithoutGnChangeOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505111 """Checks that newly added header files have corresponding GN changes.
5112 Note that this is only a heuristic. To be precise, run script:
5113 build/check_gn_headers.py.
5114 """
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195115
Sam Maiera6e76d72022-02-11 21:43:505116 def headers(f):
5117 return input_api.FilterSourceFile(
5118 f, files_to_check=(r'.+%s' % _HEADER_EXTENSIONS, ))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195119
Sam Maiera6e76d72022-02-11 21:43:505120 new_headers = []
5121 for f in input_api.AffectedSourceFiles(headers):
5122 if f.Action() != 'A':
5123 continue
5124 new_headers.append(f.LocalPath())
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195125
Sam Maiera6e76d72022-02-11 21:43:505126 def gn_files(f):
5127 return input_api.FilterSourceFile(f, files_to_check=(r'.+\.gn', ))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195128
Sam Maiera6e76d72022-02-11 21:43:505129 all_gn_changed_contents = ''
5130 for f in input_api.AffectedSourceFiles(gn_files):
5131 for _, line in f.ChangedContents():
5132 all_gn_changed_contents += line
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195133
Sam Maiera6e76d72022-02-11 21:43:505134 problems = []
5135 for header in new_headers:
5136 basename = input_api.os_path.basename(header)
5137 if basename not in all_gn_changed_contents:
5138 problems.append(header)
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195139
Sam Maiera6e76d72022-02-11 21:43:505140 if problems:
5141 return [
5142 output_api.PresubmitPromptWarning(
5143 'Missing GN changes for new header files',
5144 items=sorted(problems),
5145 long_text=
5146 'Please double check whether newly added header files need '
5147 'corresponding changes in gn or gni files.\nThis checking is only a '
5148 'heuristic. Run build/check_gn_headers.py to be precise.\n'
5149 'Read https://crbug.com/661774 for more info.')
5150 ]
5151 return []
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:195152
5153
Saagar Sanghavifceeaae2020-08-12 16:40:365154def CheckCorrectProductNameInMessages(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505155 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
Michael Giuffridad3bc8672018-10-25 22:48:025156
Sam Maiera6e76d72022-02-11 21:43:505157 This assumes we won't intentionally reference one product from the other
5158 product.
5159 """
5160 all_problems = []
5161 test_cases = [{
5162 "filename_postfix": "google_chrome_strings.grd",
5163 "correct_name": "Chrome",
5164 "incorrect_name": "Chromium",
5165 }, {
Thiago Perrotta099034f2023-06-05 18:10:205166 "filename_postfix": "google_chrome_strings.grd",
5167 "correct_name": "Chrome",
5168 "incorrect_name": "Chrome for Testing",
5169 }, {
Sam Maiera6e76d72022-02-11 21:43:505170 "filename_postfix": "chromium_strings.grd",
5171 "correct_name": "Chromium",
5172 "incorrect_name": "Chrome",
5173 }]
Michael Giuffridad3bc8672018-10-25 22:48:025174
Sam Maiera6e76d72022-02-11 21:43:505175 for test_case in test_cases:
5176 problems = []
5177 filename_filter = lambda x: x.LocalPath().endswith(test_case[
5178 "filename_postfix"])
Michael Giuffridad3bc8672018-10-25 22:48:025179
Sam Maiera6e76d72022-02-11 21:43:505180 # Check each new line. Can yield false positives in multiline comments, but
5181 # easier than trying to parse the XML because messages can have nested
5182 # children, and associating message elements with affected lines is hard.
5183 for f in input_api.AffectedSourceFiles(filename_filter):
5184 for line_num, line in f.ChangedContents():
5185 if "<message" in line or "<!--" in line or "-->" in line:
5186 continue
5187 if test_case["incorrect_name"] in line:
Thiago Perrotta099034f2023-06-05 18:10:205188 # Chrome for Testing is a special edge case: https://goo.gle/chrome-for-testing#bookmark=id.n1rat320av91
5189 if (test_case["correct_name"] == "Chromium" and line.count("Chrome") == line.count("Chrome for Testing")):
5190 continue
Sam Maiera6e76d72022-02-11 21:43:505191 problems.append("Incorrect product name in %s:%d" %
5192 (f.LocalPath(), line_num))
Michael Giuffridad3bc8672018-10-25 22:48:025193
Sam Maiera6e76d72022-02-11 21:43:505194 if problems:
5195 message = (
5196 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
5197 % (test_case["correct_name"], test_case["correct_name"],
5198 test_case["incorrect_name"]))
5199 all_problems.append(
5200 output_api.PresubmitPromptWarning(message, items=problems))
Michael Giuffridad3bc8672018-10-25 22:48:025201
Sam Maiera6e76d72022-02-11 21:43:505202 return all_problems
Michael Giuffridad3bc8672018-10-25 22:48:025203
5204
Saagar Sanghavifceeaae2020-08-12 16:40:365205def CheckForTooLargeFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505206 """Avoid large files, especially binary files, in the repository since
5207 git doesn't scale well for those. They will be in everyone's repo
5208 clones forever, forever making Chromium slower to clone and work
5209 with."""
Daniel Bratell93eb6c62019-04-29 20:13:365210
Sam Maiera6e76d72022-02-11 21:43:505211 # Uploading files to cloud storage is not trivial so we don't want
5212 # to set the limit too low, but the upper limit for "normal" large
5213 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
5214 # anything over 20 MB is exceptional.
Bruce Dawsonbb414db2022-12-27 20:21:255215 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024
Daniel Bratell93eb6c62019-04-29 20:13:365216
Sam Maiera6e76d72022-02-11 21:43:505217 too_large_files = []
5218 for f in input_api.AffectedFiles():
5219 # Check both added and modified files (but not deleted files).
5220 if f.Action() in ('A', 'M'):
5221 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Joe DeBlasio10a832f2023-04-21 20:20:185222 if size > TOO_LARGE_FILE_SIZE_LIMIT:
Sam Maiera6e76d72022-02-11 21:43:505223 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
Daniel Bratell93eb6c62019-04-29 20:13:365224
Sam Maiera6e76d72022-02-11 21:43:505225 if too_large_files:
5226 message = (
5227 'Do not commit large files to git since git scales badly for those.\n'
5228 +
5229 'Instead put the large files in cloud storage and use DEPS to\n' +
5230 'fetch them.\n' + '\n'.join(too_large_files))
5231 return [
5232 output_api.PresubmitError('Too large files found in commit',
5233 long_text=message + '\n')
5234 ]
5235 else:
5236 return []
Daniel Bratell93eb6c62019-04-29 20:13:365237
Max Morozb47503b2019-08-08 21:03:275238
Saagar Sanghavifceeaae2020-08-12 16:40:365239def CheckFuzzTargetsOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505240 """Checks specific for fuzz target sources."""
5241 EXPORTED_SYMBOLS = [
5242 'LLVMFuzzerInitialize',
5243 'LLVMFuzzerCustomMutator',
5244 'LLVMFuzzerCustomCrossOver',
5245 'LLVMFuzzerMutate',
5246 ]
Max Morozb47503b2019-08-08 21:03:275247
Sam Maiera6e76d72022-02-11 21:43:505248 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
Max Morozb47503b2019-08-08 21:03:275249
Sam Maiera6e76d72022-02-11 21:43:505250 def FilterFile(affected_file):
5251 """Ignore libFuzzer source code."""
5252 files_to_check = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
Bruce Dawson40fece62022-09-16 19:58:315253 files_to_skip = r"^third_party/libFuzzer"
Max Morozb47503b2019-08-08 21:03:275254
Sam Maiera6e76d72022-02-11 21:43:505255 return input_api.FilterSourceFile(affected_file,
5256 files_to_check=[files_to_check],
5257 files_to_skip=[files_to_skip])
Max Morozb47503b2019-08-08 21:03:275258
Sam Maiera6e76d72022-02-11 21:43:505259 files_with_missing_header = []
5260 for f in input_api.AffectedSourceFiles(FilterFile):
5261 contents = input_api.ReadFile(f, 'r')
5262 if REQUIRED_HEADER in contents:
5263 continue
Max Morozb47503b2019-08-08 21:03:275264
Sam Maiera6e76d72022-02-11 21:43:505265 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
5266 files_with_missing_header.append(f.LocalPath())
Max Morozb47503b2019-08-08 21:03:275267
Sam Maiera6e76d72022-02-11 21:43:505268 if not files_with_missing_header:
5269 return []
Max Morozb47503b2019-08-08 21:03:275270
Sam Maiera6e76d72022-02-11 21:43:505271 long_text = (
5272 'If you define any of the libFuzzer optional functions (%s), it is '
5273 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
5274 'work incorrectly on Mac (crbug.com/687076).\nNote that '
5275 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
5276 'to access command line arguments passed to the fuzzer. Instead, prefer '
5277 'static initialization and shared resources as documented in '
5278 'https://chromium.googlesource.com/chromium/src/+/main/testing/'
5279 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n'
5280 % (', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER))
Max Morozb47503b2019-08-08 21:03:275281
Sam Maiera6e76d72022-02-11 21:43:505282 return [
5283 output_api.PresubmitPromptWarning(message="Missing '%s' in:" %
5284 REQUIRED_HEADER,
5285 items=files_with_missing_header,
5286 long_text=long_text)
5287 ]
Max Morozb47503b2019-08-08 21:03:275288
5289
Mohamed Heikald048240a2019-11-12 16:57:375290def _CheckNewImagesWarning(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505291 """
5292 Warns authors who add images into the repo to make sure their images are
5293 optimized before committing.
5294 """
5295 images_added = False
5296 image_paths = []
5297 errors = []
5298 filter_lambda = lambda x: input_api.FilterSourceFile(
5299 x,
5300 files_to_skip=(('(?i).*test', r'.*\/junit\/') + input_api.
5301 DEFAULT_FILES_TO_SKIP),
5302 files_to_check=[r'.*\/(drawable|mipmap)'])
5303 for f in input_api.AffectedFiles(include_deletes=False,
5304 file_filter=filter_lambda):
5305 local_path = f.LocalPath().lower()
5306 if any(
5307 local_path.endswith(extension)
5308 for extension in _IMAGE_EXTENSIONS):
5309 images_added = True
5310 image_paths.append(f)
5311 if images_added:
5312 errors.append(
5313 output_api.PresubmitPromptWarning(
5314 'It looks like you are trying to commit some images. If these are '
5315 'non-test-only images, please make sure to read and apply the tips in '
5316 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
5317 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
5318 'FYI only and will not block your CL on the CQ.', image_paths))
5319 return errors
Mohamed Heikald048240a2019-11-12 16:57:375320
5321
Saagar Sanghavifceeaae2020-08-12 16:40:365322def ChecksAndroidSpecificOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505323 """Groups upload checks that target android code."""
5324 results = []
5325 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
5326 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
5327 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
5328 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:505329 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
5330 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
5331 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
5332 results.extend(_CheckNewImagesWarning(input_api, output_api))
5333 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
5334 results.extend(_CheckAndroidInfoBarDeprecation(input_api, output_api))
5335 return results
5336
Becky Zhou7c69b50992018-12-10 19:37:575337
Saagar Sanghavifceeaae2020-08-12 16:40:365338def ChecksAndroidSpecificOnCommit(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505339 """Groups commit checks that target android code."""
5340 results = []
5341 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
5342 return results
dgnaa68d5e2015-06-10 10:08:225343
Chris Hall59f8d0c72020-05-01 07:31:195344# TODO(chrishall): could we additionally match on any path owned by
5345# ui/accessibility/OWNERS ?
5346_ACCESSIBILITY_PATHS = (
Bruce Dawson40fece62022-09-16 19:58:315347 r"^chrome/browser.*/accessibility/",
5348 r"^chrome/browser/extensions/api/automation.*/",
5349 r"^chrome/renderer/extensions/accessibility_.*",
5350 r"^chrome/tests/data/accessibility/",
5351 r"^content/browser/accessibility/",
5352 r"^content/renderer/accessibility/",
5353 r"^content/tests/data/accessibility/",
5354 r"^extensions/renderer/api/automation/",
Katie Dektar58ef07b2022-09-27 13:19:175355 r"^services/accessibility/",
Abigail Klein7a63c572024-02-28 20:45:095356 r"^services/screen_ai/",
Bruce Dawson40fece62022-09-16 19:58:315357 r"^ui/accessibility/",
5358 r"^ui/views/accessibility/",
Chris Hall59f8d0c72020-05-01 07:31:195359)
5360
Saagar Sanghavifceeaae2020-08-12 16:40:365361def CheckAccessibilityRelnotesField(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505362 """Checks that commits to accessibility code contain an AX-Relnotes field in
5363 their commit message."""
Chris Hall59f8d0c72020-05-01 07:31:195364
Sam Maiera6e76d72022-02-11 21:43:505365 def FileFilter(affected_file):
5366 paths = _ACCESSIBILITY_PATHS
5367 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Chris Hall59f8d0c72020-05-01 07:31:195368
Sam Maiera6e76d72022-02-11 21:43:505369 # Only consider changes affecting accessibility paths.
5370 if not any(input_api.AffectedFiles(file_filter=FileFilter)):
5371 return []
Akihiro Ota08108e542020-05-20 15:30:535372
Sam Maiera6e76d72022-02-11 21:43:505373 # AX-Relnotes can appear in either the description or the footer.
5374 # When searching the description, require 'AX-Relnotes:' to appear at the
5375 # beginning of a line.
5376 ax_regex = input_api.re.compile('ax-relnotes[:=]')
5377 description_has_relnotes = any(
5378 ax_regex.match(line)
5379 for line in input_api.change.DescriptionText().lower().splitlines())
Chris Hall59f8d0c72020-05-01 07:31:195380
Sam Maiera6e76d72022-02-11 21:43:505381 footer_relnotes = input_api.change.GitFootersFromDescription().get(
5382 'AX-Relnotes', [])
5383 if description_has_relnotes or footer_relnotes:
5384 return []
Chris Hall59f8d0c72020-05-01 07:31:195385
Sam Maiera6e76d72022-02-11 21:43:505386 # TODO(chrishall): link to Relnotes documentation in message.
5387 message = (
5388 "Missing 'AX-Relnotes:' field required for accessibility changes"
5389 "\n please add 'AX-Relnotes: [release notes].' to describe any "
5390 "user-facing changes"
5391 "\n otherwise add 'AX-Relnotes: n/a.' if this change has no "
5392 "user-facing effects"
5393 "\n if this is confusing or annoying then please contact members "
5394 "of ui/accessibility/OWNERS.")
5395
5396 return [output_api.PresubmitNotifyResult(message)]
dgnaa68d5e2015-06-10 10:08:225397
Mark Schillacie5a0be22022-01-19 00:38:395398
5399_ACCESSIBILITY_EVENTS_TEST_PATH = (
Bruce Dawson40fece62022-09-16 19:58:315400 r"^content/test/data/accessibility/event/.*\.html",
Mark Schillacie5a0be22022-01-19 00:38:395401)
5402
5403_ACCESSIBILITY_TREE_TEST_PATH = (
Aaron Leventhal267119f2023-08-18 22:45:345404 r"^content/test/data/accessibility/accname/"
5405 ".*-expected-(mac|win|uia-win|auralinux).txt",
5406 r"^content/test/data/accessibility/aria/"
5407 ".*-expected-(mac|win|uia-win|auralinux).txt",
5408 r"^content/test/data/accessibility/css/"
5409 ".*-expected-(mac|win|uia-win|auralinux).txt",
5410 r"^content/test/data/accessibility/event/"
5411 ".*-expected-(mac|win|uia-win|auralinux).txt",
5412 r"^content/test/data/accessibility/html/"
5413 ".*-expected-(mac|win|uia-win|auralinux).txt",
Mark Schillacie5a0be22022-01-19 00:38:395414)
5415
5416_ACCESSIBILITY_ANDROID_EVENTS_TEST_PATH = (
Bruce Dawson40fece62022-09-16 19:58:315417 r"^.*/WebContentsAccessibilityEventsTest\.java",
Mark Schillacie5a0be22022-01-19 00:38:395418)
5419
5420_ACCESSIBILITY_ANDROID_TREE_TEST_PATH = (
Bruce Dawson40fece62022-09-16 19:58:315421 r"^.*/WebContentsAccessibilityTreeTest\.java",
Mark Schillacie5a0be22022-01-19 00:38:395422)
5423
5424def CheckAccessibilityEventsTestsAreIncludedForAndroid(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505425 """Checks that commits that include a newly added, renamed/moved, or deleted
5426 test in the DumpAccessibilityEventsTest suite also includes a corresponding
5427 change to the Android test."""
Mark Schillacie5a0be22022-01-19 00:38:395428
Sam Maiera6e76d72022-02-11 21:43:505429 def FilePathFilter(affected_file):
5430 paths = _ACCESSIBILITY_EVENTS_TEST_PATH
5431 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395432
Sam Maiera6e76d72022-02-11 21:43:505433 def AndroidFilePathFilter(affected_file):
5434 paths = _ACCESSIBILITY_ANDROID_EVENTS_TEST_PATH
5435 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395436
Sam Maiera6e76d72022-02-11 21:43:505437 # Only consider changes in the events test data path with html type.
5438 if not any(
5439 input_api.AffectedFiles(include_deletes=True,
5440 file_filter=FilePathFilter)):
5441 return []
Mark Schillacie5a0be22022-01-19 00:38:395442
Sam Maiera6e76d72022-02-11 21:43:505443 # If the commit contains any change to the Android test file, ignore.
5444 if any(
5445 input_api.AffectedFiles(include_deletes=True,
5446 file_filter=AndroidFilePathFilter)):
5447 return []
Mark Schillacie5a0be22022-01-19 00:38:395448
Sam Maiera6e76d72022-02-11 21:43:505449 # Only consider changes that are adding/renaming or deleting a file
5450 message = []
5451 for f in input_api.AffectedFiles(include_deletes=True,
5452 file_filter=FilePathFilter):
Aaron Leventhal267119f2023-08-18 22:45:345453 if f.Action() == 'A':
Sam Maiera6e76d72022-02-11 21:43:505454 message = (
Aaron Leventhal267119f2023-08-18 22:45:345455 "It appears that you are adding platform expectations for a"
Aaron Leventhal0de81072023-08-21 21:26:525456 "\ndump_accessibility_events* test, but have not included"
Sam Maiera6e76d72022-02-11 21:43:505457 "\na corresponding change for Android."
Aaron Leventhal267119f2023-08-18 22:45:345458 "\nPlease include the test from:"
Sam Maiera6e76d72022-02-11 21:43:505459 "\n content/public/android/javatests/src/org/chromium/"
5460 "content/browser/accessibility/"
5461 "WebContentsAccessibilityEventsTest.java"
5462 "\nIf this message is confusing or annoying, please contact"
5463 "\nmembers of ui/accessibility/OWNERS.")
Mark Schillacie5a0be22022-01-19 00:38:395464
Sam Maiera6e76d72022-02-11 21:43:505465 # If no message was set, return empty.
5466 if not len(message):
5467 return []
5468
5469 return [output_api.PresubmitPromptWarning(message)]
5470
Mark Schillacie5a0be22022-01-19 00:38:395471
5472def CheckAccessibilityTreeTestsAreIncludedForAndroid(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505473 """Checks that commits that include a newly added, renamed/moved, or deleted
5474 test in the DumpAccessibilityTreeTest suite also includes a corresponding
5475 change to the Android test."""
Mark Schillacie5a0be22022-01-19 00:38:395476
Sam Maiera6e76d72022-02-11 21:43:505477 def FilePathFilter(affected_file):
5478 paths = _ACCESSIBILITY_TREE_TEST_PATH
5479 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395480
Sam Maiera6e76d72022-02-11 21:43:505481 def AndroidFilePathFilter(affected_file):
5482 paths = _ACCESSIBILITY_ANDROID_TREE_TEST_PATH
5483 return input_api.FilterSourceFile(affected_file, files_to_check=paths)
Mark Schillacie5a0be22022-01-19 00:38:395484
Sam Maiera6e76d72022-02-11 21:43:505485 # Only consider changes in the various tree test data paths with html type.
5486 if not any(
5487 input_api.AffectedFiles(include_deletes=True,
5488 file_filter=FilePathFilter)):
5489 return []
Mark Schillacie5a0be22022-01-19 00:38:395490
Sam Maiera6e76d72022-02-11 21:43:505491 # If the commit contains any change to the Android test file, ignore.
5492 if any(
5493 input_api.AffectedFiles(include_deletes=True,
5494 file_filter=AndroidFilePathFilter)):
5495 return []
Mark Schillacie5a0be22022-01-19 00:38:395496
Sam Maiera6e76d72022-02-11 21:43:505497 # Only consider changes that are adding/renaming or deleting a file
5498 message = []
5499 for f in input_api.AffectedFiles(include_deletes=True,
5500 file_filter=FilePathFilter):
Aaron Leventhal0de81072023-08-21 21:26:525501 if f.Action() == 'A':
Sam Maiera6e76d72022-02-11 21:43:505502 message = (
Aaron Leventhal0de81072023-08-21 21:26:525503 "It appears that you are adding platform expectations for a"
5504 "\ndump_accessibility_tree* test, but have not included"
Sam Maiera6e76d72022-02-11 21:43:505505 "\na corresponding change for Android."
5506 "\nPlease include (or remove) the test from:"
5507 "\n content/public/android/javatests/src/org/chromium/"
5508 "content/browser/accessibility/"
5509 "WebContentsAccessibilityTreeTest.java"
5510 "\nIf this message is confusing or annoying, please contact"
5511 "\nmembers of ui/accessibility/OWNERS.")
Mark Schillacie5a0be22022-01-19 00:38:395512
Sam Maiera6e76d72022-02-11 21:43:505513 # If no message was set, return empty.
5514 if not len(message):
5515 return []
5516
5517 return [output_api.PresubmitPromptWarning(message)]
Mark Schillacie5a0be22022-01-19 00:38:395518
5519
Bruce Dawson33806592022-11-16 01:44:515520def CheckEsLintConfigChanges(input_api, output_api):
5521 """Suggest using "git cl presubmit --files" when .eslintrc.js files are
5522 modified. This is important because enabling an error in .eslintrc.js can
5523 trigger errors in any .js or .ts files in its directory, leading to hidden
5524 presubmit errors."""
5525 results = []
5526 eslint_filter = lambda f: input_api.FilterSourceFile(
5527 f, files_to_check=[r'.*\.eslintrc\.js$'])
5528 for f in input_api.AffectedFiles(include_deletes=False,
5529 file_filter=eslint_filter):
5530 local_dir = input_api.os_path.dirname(f.LocalPath())
5531 # Use / characters so that the commands printed work on any OS.
5532 local_dir = local_dir.replace(input_api.os_path.sep, '/')
5533 if local_dir:
5534 local_dir += '/'
5535 results.append(
5536 output_api.PresubmitNotifyResult(
5537 '%(file)s modified. Consider running \'git cl presubmit --files '
5538 '"%(dir)s*.js;%(dir)s*.ts"\' in order to check and fix the affected '
5539 'files before landing this change.' %
5540 { 'file' : f.LocalPath(), 'dir' : local_dir}))
5541 return results
5542
5543
seanmccullough4a9356252021-04-08 19:54:095544# string pattern, sequence of strings to show when pattern matches,
5545# error flag. True if match is a presubmit error, otherwise it's a warning.
5546_NON_INCLUSIVE_TERMS = (
5547 (
5548 # Note that \b pattern in python re is pretty particular. In this
5549 # regexp, 'class WhiteList ...' will match, but 'class FooWhiteList
5550 # ...' will not. This may require some tweaking to catch these cases
5551 # without triggering a lot of false positives. Leaving it naive and
5552 # less matchy for now.
Josip Sokcevic9d2806a02023-12-13 03:04:025553 r'/(?i)\b((black|white)list|master|slave)\b', # nocheck
seanmccullough4a9356252021-04-08 19:54:095554 (
5555 'Please don\'t use blacklist, whitelist, ' # nocheck
5556 'or slave in your', # nocheck
5557 'code and make every effort to use other terms. Using "// nocheck"',
5558 '"# nocheck" or "<!-- nocheck -->"',
5559 'at the end of the offending line will bypass this PRESUBMIT error',
5560 'but avoid using this whenever possible. Reach out to',
5561 '[email protected] if you have questions'),
5562 True),)
5563
Saagar Sanghavifceeaae2020-08-12 16:40:365564def ChecksCommon(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505565 """Checks common to both upload and commit."""
5566 results = []
Eric Boren6fd2b932018-01-25 15:05:085567 results.extend(
Sam Maiera6e76d72022-02-11 21:43:505568 input_api.canned_checks.PanProjectChecks(
5569 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:085570
Sam Maiera6e76d72022-02-11 21:43:505571 author = input_api.change.author_email
5572 if author and author not in _KNOWN_ROBOTS:
5573 results.extend(
5574 input_api.canned_checks.CheckAuthorizedAuthor(
5575 input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:245576
Sam Maiera6e76d72022-02-11 21:43:505577 results.extend(
5578 input_api.canned_checks.CheckChangeHasNoTabs(
5579 input_api,
5580 output_api,
5581 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
5582 results.extend(
5583 input_api.RunTests(
5584 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Edward Lesmesce51df52020-08-04 22:10:175585
Bruce Dawsonc8054482022-03-28 15:33:375586 dirmd = 'dirmd.bat' if input_api.is_windows else 'dirmd'
Sam Maiera6e76d72022-02-11 21:43:505587 dirmd_bin = input_api.os_path.join(input_api.PresubmitLocalPath(),
Bruce Dawsonc8054482022-03-28 15:33:375588 'third_party', 'depot_tools', dirmd)
Sam Maiera6e76d72022-02-11 21:43:505589 results.extend(
5590 input_api.RunTests(
5591 input_api.canned_checks.CheckDirMetadataFormat(
5592 input_api, output_api, dirmd_bin)))
5593 results.extend(
5594 input_api.canned_checks.CheckOwnersDirMetadataExclusive(
5595 input_api, output_api))
5596 results.extend(
5597 input_api.canned_checks.CheckNoNewMetadataInOwners(
5598 input_api, output_api))
5599 results.extend(
5600 input_api.canned_checks.CheckInclusiveLanguage(
5601 input_api,
5602 output_api,
5603 excluded_directories_relative_path=[
5604 'infra', 'inclusive_language_presubmit_exempt_dirs.txt'
5605 ],
5606 non_inclusive_terms=_NON_INCLUSIVE_TERMS))
Dirk Prankee3c9c62d2021-05-18 18:35:595607
Aleksey Khoroshilov2978c942022-06-13 16:14:125608 presubmit_py_filter = lambda f: input_api.FilterSourceFile(
Bruce Dawson696963f2022-09-13 01:15:475609 f, files_to_check=[r'.*PRESUBMIT\.py$'])
Aleksey Khoroshilov2978c942022-06-13 16:14:125610 for f in input_api.AffectedFiles(include_deletes=False,
5611 file_filter=presubmit_py_filter):
5612 full_path = input_api.os_path.dirname(f.AbsoluteLocalPath())
5613 test_file = input_api.os_path.join(full_path, 'PRESUBMIT_test.py')
5614 # The PRESUBMIT.py file (and the directory containing it) might have
5615 # been affected by being moved or removed, so only try to run the tests
5616 # if they still exist.
5617 if not input_api.os_path.exists(test_file):
5618 continue
Sam Maiera6e76d72022-02-11 21:43:505619
Aleksey Khoroshilov2978c942022-06-13 16:14:125620 results.extend(
5621 input_api.canned_checks.RunUnitTestsInDirectory(
5622 input_api,
5623 output_api,
5624 full_path,
Takuto Ikuta40def482023-06-02 02:23:495625 files_to_check=[r'^PRESUBMIT_test\.py$']))
Sam Maiera6e76d72022-02-11 21:43:505626 return results
[email protected]1f7b4172010-01-28 01:17:345627
[email protected]b337cb5b2011-01-23 21:24:055628
Saagar Sanghavifceeaae2020-08-12 16:40:365629def CheckPatchFiles(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505630 problems = [
5631 f.LocalPath() for f in input_api.AffectedFiles()
5632 if f.LocalPath().endswith(('.orig', '.rej'))
5633 ]
5634 # Cargo.toml.orig files are part of third-party crates downloaded from
5635 # crates.io and should be included.
5636 problems = [f for f in problems if not f.endswith('Cargo.toml.orig')]
5637 if problems:
5638 return [
5639 output_api.PresubmitError("Don't commit .rej and .orig files.",
5640 problems)
5641 ]
5642 else:
5643 return []
[email protected]b8079ae4a2012-12-05 19:56:495644
5645
Saagar Sanghavifceeaae2020-08-12 16:40:365646def CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505647 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
5648 macro_re = input_api.re.compile(
5649 r'^\s*#(el)?if.*\bdefined\(((COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
5650 include_re = input_api.re.compile(r'^#include\s+"build/build_config.h"',
5651 input_api.re.MULTILINE)
5652 extension_re = input_api.re.compile(r'\.[a-z]+$')
5653 errors = []
Bruce Dawsonf7679202022-08-09 20:24:005654 config_h_file = input_api.os_path.join('build', 'build_config.h')
Sam Maiera6e76d72022-02-11 21:43:505655 for f in input_api.AffectedFiles(include_deletes=False):
Bruce Dawsonf7679202022-08-09 20:24:005656 # The build-config macros are allowed to be used in build_config.h
5657 # without including itself.
5658 if f.LocalPath() == config_h_file:
5659 continue
Sam Maiera6e76d72022-02-11 21:43:505660 if not f.LocalPath().endswith(
5661 ('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
5662 continue
5663 found_line_number = None
5664 found_macro = None
5665 all_lines = input_api.ReadFile(f, 'r').splitlines()
5666 for line_num, line in enumerate(all_lines):
5667 match = macro_re.search(line)
5668 if match:
5669 found_line_number = line_num
5670 found_macro = match.group(2)
5671 break
5672 if not found_line_number:
5673 continue
Kent Tamura5a8755d2017-06-29 23:37:075674
Sam Maiera6e76d72022-02-11 21:43:505675 found_include_line = -1
5676 for line_num, line in enumerate(all_lines):
5677 if include_re.search(line):
5678 found_include_line = line_num
5679 break
5680 if found_include_line >= 0 and found_include_line < found_line_number:
5681 continue
Kent Tamura5a8755d2017-06-29 23:37:075682
Sam Maiera6e76d72022-02-11 21:43:505683 if not f.LocalPath().endswith('.h'):
5684 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
5685 try:
5686 content = input_api.ReadFile(primary_header_path, 'r')
5687 if include_re.search(content):
5688 continue
5689 except IOError:
5690 pass
5691 errors.append('%s:%d %s macro is used without first including build/'
5692 'build_config.h.' %
5693 (f.LocalPath(), found_line_number, found_macro))
5694 if errors:
5695 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
5696 return []
Kent Tamura5a8755d2017-06-29 23:37:075697
5698
Lei Zhang1c12a22f2021-05-12 11:28:455699def CheckForSuperfluousStlIncludesInHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505700 stl_include_re = input_api.re.compile(r'^#include\s+<('
5701 r'algorithm|'
5702 r'array|'
5703 r'limits|'
5704 r'list|'
5705 r'map|'
5706 r'memory|'
5707 r'queue|'
5708 r'set|'
5709 r'string|'
5710 r'unordered_map|'
5711 r'unordered_set|'
5712 r'utility|'
5713 r'vector)>')
5714 std_namespace_re = input_api.re.compile(r'std::')
5715 errors = []
5716 for f in input_api.AffectedFiles():
5717 if not _IsCPlusPlusHeaderFile(input_api, f.LocalPath()):
5718 continue
Lei Zhang1c12a22f2021-05-12 11:28:455719
Sam Maiera6e76d72022-02-11 21:43:505720 uses_std_namespace = False
5721 has_stl_include = False
5722 for line in f.NewContents():
5723 if has_stl_include and uses_std_namespace:
5724 break
Lei Zhang1c12a22f2021-05-12 11:28:455725
Sam Maiera6e76d72022-02-11 21:43:505726 if not has_stl_include and stl_include_re.search(line):
5727 has_stl_include = True
5728 continue
Lei Zhang1c12a22f2021-05-12 11:28:455729
Bruce Dawson4a5579a2022-04-08 17:11:365730 if not uses_std_namespace and (std_namespace_re.search(line)
5731 or 'no-std-usage-because-pch-file' in line):
Sam Maiera6e76d72022-02-11 21:43:505732 uses_std_namespace = True
5733 continue
Lei Zhang1c12a22f2021-05-12 11:28:455734
Sam Maiera6e76d72022-02-11 21:43:505735 if has_stl_include and not uses_std_namespace:
5736 errors.append(
5737 '%s: Includes STL header(s) but does not reference std::' %
5738 f.LocalPath())
5739 if errors:
5740 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
5741 return []
Lei Zhang1c12a22f2021-05-12 11:28:455742
5743
Xiaohan Wang42d96c22022-01-20 17:23:115744def _CheckForDeprecatedOSMacrosInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:505745 """Check for sensible looking, totally invalid OS macros."""
5746 preprocessor_statement = input_api.re.compile(r'^\s*#')
5747 os_macro = input_api.re.compile(r'defined\(OS_([^)]+)\)')
5748 results = []
5749 for lnum, line in f.ChangedContents():
5750 if preprocessor_statement.search(line):
5751 for match in os_macro.finditer(line):
5752 results.append(
5753 ' %s:%d: %s' %
5754 (f.LocalPath(), lnum, 'defined(OS_' + match.group(1) +
5755 ') -> BUILDFLAG(IS_' + match.group(1) + ')'))
5756 return results
[email protected]b00342e7f2013-03-26 16:21:545757
5758
Xiaohan Wang42d96c22022-01-20 17:23:115759def CheckForDeprecatedOSMacros(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505760 """Check all affected files for invalid OS macros."""
5761 bad_macros = []
Bruce Dawsonf7679202022-08-09 20:24:005762 # The OS_ macros are allowed to be used in build/build_config.h.
5763 config_h_file = input_api.os_path.join('build', 'build_config.h')
Sam Maiera6e76d72022-02-11 21:43:505764 for f in input_api.AffectedSourceFiles(None):
Bruce Dawsonf7679202022-08-09 20:24:005765 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')) \
5766 and f.LocalPath() != config_h_file:
Sam Maiera6e76d72022-02-11 21:43:505767 bad_macros.extend(_CheckForDeprecatedOSMacrosInFile(input_api, f))
[email protected]b00342e7f2013-03-26 16:21:545768
Sam Maiera6e76d72022-02-11 21:43:505769 if not bad_macros:
5770 return []
[email protected]b00342e7f2013-03-26 16:21:545771
Sam Maiera6e76d72022-02-11 21:43:505772 return [
5773 output_api.PresubmitError(
5774 'OS macros have been deprecated. Please use BUILDFLAGs instead (still '
5775 'defined in build_config.h):', bad_macros)
5776 ]
[email protected]b00342e7f2013-03-26 16:21:545777
lliabraa35bab3932014-10-01 12:16:445778
5779def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
Sam Maiera6e76d72022-02-11 21:43:505780 """Check all affected files for invalid "if defined" macros."""
5781 ALWAYS_DEFINED_MACROS = (
5782 "TARGET_CPU_PPC",
5783 "TARGET_CPU_PPC64",
5784 "TARGET_CPU_68K",
5785 "TARGET_CPU_X86",
5786 "TARGET_CPU_ARM",
5787 "TARGET_CPU_MIPS",
5788 "TARGET_CPU_SPARC",
5789 "TARGET_CPU_ALPHA",
5790 "TARGET_IPHONE_SIMULATOR",
5791 "TARGET_OS_EMBEDDED",
5792 "TARGET_OS_IPHONE",
5793 "TARGET_OS_MAC",
5794 "TARGET_OS_UNIX",
5795 "TARGET_OS_WIN32",
5796 )
5797 ifdef_macro = input_api.re.compile(
5798 r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
5799 results = []
5800 for lnum, line in f.ChangedContents():
5801 for match in ifdef_macro.finditer(line):
5802 if match.group(1) in ALWAYS_DEFINED_MACROS:
5803 always_defined = ' %s is always defined. ' % match.group(1)
5804 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
5805 results.append(
5806 ' %s:%d %s\n\t%s' %
5807 (f.LocalPath(), lnum, always_defined, did_you_mean))
5808 return results
lliabraa35bab3932014-10-01 12:16:445809
5810
Saagar Sanghavifceeaae2020-08-12 16:40:365811def CheckForInvalidIfDefinedMacros(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505812 """Check all affected files for invalid "if defined" macros."""
5813 bad_macros = []
5814 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
5815 for f in input_api.AffectedFiles():
5816 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
5817 continue
5818 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
5819 bad_macros.extend(
5820 _CheckForInvalidIfDefinedMacrosInFile(input_api, f))
lliabraa35bab3932014-10-01 12:16:445821
Sam Maiera6e76d72022-02-11 21:43:505822 if not bad_macros:
5823 return []
lliabraa35bab3932014-10-01 12:16:445824
Sam Maiera6e76d72022-02-11 21:43:505825 return [
5826 output_api.PresubmitError(
5827 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
5828 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
5829 bad_macros)
5830 ]
lliabraa35bab3932014-10-01 12:16:445831
5832
Saagar Sanghavifceeaae2020-08-12 16:40:365833def CheckForIPCRules(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505834 """Check for same IPC rules described in
5835 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
5836 """
5837 base_pattern = r'IPC_ENUM_TRAITS\('
5838 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
5839 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
mlamouria82272622014-09-16 18:45:045840
Sam Maiera6e76d72022-02-11 21:43:505841 problems = []
5842 for f in input_api.AffectedSourceFiles(None):
5843 local_path = f.LocalPath()
5844 if not local_path.endswith('.h'):
5845 continue
5846 for line_number, line in f.ChangedContents():
5847 if inclusion_pattern.search(
5848 line) and not comment_pattern.search(line):
5849 problems.append('%s:%d\n %s' %
5850 (local_path, line_number, line.strip()))
mlamouria82272622014-09-16 18:45:045851
Sam Maiera6e76d72022-02-11 21:43:505852 if problems:
5853 return [
5854 output_api.PresubmitPromptWarning(_IPC_ENUM_TRAITS_DEPRECATED,
5855 problems)
5856 ]
5857 else:
5858 return []
mlamouria82272622014-09-16 18:45:045859
[email protected]b00342e7f2013-03-26 16:21:545860
Saagar Sanghavifceeaae2020-08-12 16:40:365861def CheckForLongPathnames(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505862 """Check to make sure no files being submitted have long paths.
5863 This causes issues on Windows.
5864 """
5865 problems = []
5866 for f in input_api.AffectedTestableFiles():
5867 local_path = f.LocalPath()
5868 # Windows has a path limit of 260 characters. Limit path length to 200 so
5869 # that we have some extra for the prefix on dev machines and the bots.
5870 if len(local_path) > 200:
5871 problems.append(local_path)
Stephen Martinis97a394142018-06-07 23:06:055872
Sam Maiera6e76d72022-02-11 21:43:505873 if problems:
5874 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
5875 else:
5876 return []
Stephen Martinis97a394142018-06-07 23:06:055877
5878
Saagar Sanghavifceeaae2020-08-12 16:40:365879def CheckForIncludeGuards(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:505880 """Check that header files have proper guards against multiple inclusion.
5881 If a file should not have such guards (and it probably should) then it
Bruce Dawson4a5579a2022-04-08 17:11:365882 should include the string "no-include-guard-because-multiply-included" or
5883 "no-include-guard-because-pch-file".
Sam Maiera6e76d72022-02-11 21:43:505884 """
Daniel Bratell8ba52722018-03-02 16:06:145885
Sam Maiera6e76d72022-02-11 21:43:505886 def is_chromium_header_file(f):
5887 # We only check header files under the control of the Chromium
mikt84d6c712024-03-27 13:29:035888 # project. This excludes:
5889 # - third_party/*, except blink.
5890 # - base/allocator/partition_allocator/: PartitionAlloc is a standalone
5891 # library used outside of Chrome. Includes are referenced from its
5892 # own base directory. It has its own `CheckForIncludeGuards`
5893 # PRESUBMIT.py check.
5894 # - *_message_generator.h: They use include guards in a special,
5895 # non-typical way.
Sam Maiera6e76d72022-02-11 21:43:505896 file_with_path = input_api.os_path.normpath(f.LocalPath())
5897 return (file_with_path.endswith('.h')
5898 and not file_with_path.endswith('_message_generator.h')
Bruce Dawson4c4c2922022-05-02 18:07:335899 and not file_with_path.endswith('com_imported_mstscax.h')
mikt84d6c712024-03-27 13:29:035900 and not file_with_path.startswith('base/allocator/partition_allocator')
Sam Maiera6e76d72022-02-11 21:43:505901 and (not file_with_path.startswith('third_party')
5902 or file_with_path.startswith(
5903 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:145904
Sam Maiera6e76d72022-02-11 21:43:505905 def replace_special_with_underscore(string):
5906 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:145907
Sam Maiera6e76d72022-02-11 21:43:505908 errors = []
Daniel Bratell8ba52722018-03-02 16:06:145909
Sam Maiera6e76d72022-02-11 21:43:505910 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
5911 guard_name = None
5912 guard_line_number = None
5913 seen_guard_end = False
Daniel Bratell8ba52722018-03-02 16:06:145914
Sam Maiera6e76d72022-02-11 21:43:505915 file_with_path = input_api.os_path.normpath(f.LocalPath())
5916 base_file_name = input_api.os_path.splitext(
5917 input_api.os_path.basename(file_with_path))[0]
5918 upper_base_file_name = base_file_name.upper()
Daniel Bratell8ba52722018-03-02 16:06:145919
Sam Maiera6e76d72022-02-11 21:43:505920 expected_guard = replace_special_with_underscore(
5921 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:145922
Sam Maiera6e76d72022-02-11 21:43:505923 # For "path/elem/file_name.h" we should really only accept
5924 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
5925 # are too many (1000+) files with slight deviations from the
5926 # coding style. The most important part is that the include guard
5927 # is there, and that it's unique, not the name so this check is
5928 # forgiving for existing files.
5929 #
5930 # As code becomes more uniform, this could be made stricter.
Daniel Bratell8ba52722018-03-02 16:06:145931
Sam Maiera6e76d72022-02-11 21:43:505932 guard_name_pattern_list = [
5933 # Anything with the right suffix (maybe with an extra _).
5934 r'\w+_H__?',
Daniel Bratell8ba52722018-03-02 16:06:145935
Sam Maiera6e76d72022-02-11 21:43:505936 # To cover include guards with old Blink style.
5937 r'\w+_h',
Daniel Bratell8ba52722018-03-02 16:06:145938
Sam Maiera6e76d72022-02-11 21:43:505939 # Anything including the uppercase name of the file.
5940 r'\w*' + input_api.re.escape(
5941 replace_special_with_underscore(upper_base_file_name)) +
5942 r'\w*',
5943 ]
5944 guard_name_pattern = '|'.join(guard_name_pattern_list)
5945 guard_pattern = input_api.re.compile(r'#ifndef\s+(' +
5946 guard_name_pattern + ')')
Daniel Bratell8ba52722018-03-02 16:06:145947
Sam Maiera6e76d72022-02-11 21:43:505948 for line_number, line in enumerate(f.NewContents()):
Bruce Dawson4a5579a2022-04-08 17:11:365949 if ('no-include-guard-because-multiply-included' in line
5950 or 'no-include-guard-because-pch-file' in line):
Sam Maiera6e76d72022-02-11 21:43:505951 guard_name = 'DUMMY' # To not trigger check outside the loop.
5952 break
Daniel Bratell8ba52722018-03-02 16:06:145953
Sam Maiera6e76d72022-02-11 21:43:505954 if guard_name is None:
5955 match = guard_pattern.match(line)
5956 if match:
5957 guard_name = match.group(1)
5958 guard_line_number = line_number
Daniel Bratell8ba52722018-03-02 16:06:145959
Sam Maiera6e76d72022-02-11 21:43:505960 # We allow existing files to use include guards whose names
5961 # don't match the chromium style guide, but new files should
5962 # get it right.
Bruce Dawson6cc154e2022-04-12 20:39:495963 if guard_name != expected_guard:
Bruce Dawson95eb7562022-09-14 15:27:165964 if f.Action() == 'A': # If file was just 'A'dded
Sam Maiera6e76d72022-02-11 21:43:505965 errors.append(
5966 output_api.PresubmitPromptWarning(
5967 'Header using the wrong include guard name %s'
5968 % guard_name, [
5969 '%s:%d' %
5970 (f.LocalPath(), line_number + 1)
5971 ], 'Expected: %r\nFound: %r' %
5972 (expected_guard, guard_name)))
5973 else:
5974 # The line after #ifndef should have a #define of the same name.
5975 if line_number == guard_line_number + 1:
5976 expected_line = '#define %s' % guard_name
5977 if line != expected_line:
5978 errors.append(
5979 output_api.PresubmitPromptWarning(
5980 'Missing "%s" for include guard' %
5981 expected_line,
5982 ['%s:%d' % (f.LocalPath(), line_number + 1)],
5983 'Expected: %r\nGot: %r' %
5984 (expected_line, line)))
Daniel Bratell8ba52722018-03-02 16:06:145985
Sam Maiera6e76d72022-02-11 21:43:505986 if not seen_guard_end and line == '#endif // %s' % guard_name:
5987 seen_guard_end = True
5988 elif seen_guard_end:
5989 if line.strip() != '':
5990 errors.append(
5991 output_api.PresubmitPromptWarning(
5992 'Include guard %s not covering the whole file'
5993 % (guard_name), [f.LocalPath()]))
5994 break # Nothing else to check and enough to warn once.
Daniel Bratell8ba52722018-03-02 16:06:145995
Sam Maiera6e76d72022-02-11 21:43:505996 if guard_name is None:
5997 errors.append(
5998 output_api.PresubmitPromptWarning(
Bruce Dawson32114b62022-04-11 16:45:495999 'Missing include guard in %s\n'
Sam Maiera6e76d72022-02-11 21:43:506000 'Recommended name: %s\n'
6001 'This check can be disabled by having the string\n'
Bruce Dawson4a5579a2022-04-08 17:11:366002 '"no-include-guard-because-multiply-included" or\n'
6003 '"no-include-guard-because-pch-file" in the header.'
Sam Maiera6e76d72022-02-11 21:43:506004 % (f.LocalPath(), expected_guard)))
6005
6006 return errors
Daniel Bratell8ba52722018-03-02 16:06:146007
6008
Saagar Sanghavifceeaae2020-08-12 16:40:366009def CheckForWindowsLineEndings(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506010 """Check source code and known ascii text files for Windows style line
6011 endings.
6012 """
Bruce Dawson5efbdc652022-04-11 19:29:516013 known_text_files = r'.*\.(txt|html|htm|py|gyp|gypi|gn|isolate|icon)$'
mostynbb639aca52015-01-07 20:31:236014
Sam Maiera6e76d72022-02-11 21:43:506015 file_inclusion_pattern = (known_text_files,
6016 r'.+%s' % _IMPLEMENTATION_EXTENSIONS,
6017 r'.+%s' % _HEADER_EXTENSIONS)
mostynbb639aca52015-01-07 20:31:236018
Sam Maiera6e76d72022-02-11 21:43:506019 problems = []
6020 source_file_filter = lambda f: input_api.FilterSourceFile(
6021 f, files_to_check=file_inclusion_pattern, files_to_skip=None)
6022 for f in input_api.AffectedSourceFiles(source_file_filter):
Bruce Dawson5efbdc652022-04-11 19:29:516023 # Ignore test files that contain crlf intentionally.
6024 if f.LocalPath().endswith('crlf.txt'):
Daniel Chenga37c03db2022-05-12 17:20:346025 continue
Sam Maiera6e76d72022-02-11 21:43:506026 include_file = False
6027 for line in input_api.ReadFile(f, 'r').splitlines(True):
6028 if line.endswith('\r\n'):
6029 include_file = True
6030 if include_file:
6031 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:236032
Sam Maiera6e76d72022-02-11 21:43:506033 if problems:
6034 return [
6035 output_api.PresubmitPromptWarning(
6036 'Are you sure that you want '
6037 'these files to contain Windows style line endings?\n' +
6038 '\n'.join(problems))
6039 ]
mostynbb639aca52015-01-07 20:31:236040
Sam Maiera6e76d72022-02-11 21:43:506041 return []
6042
mostynbb639aca52015-01-07 20:31:236043
Evan Stade6cfc964c12021-05-18 20:21:166044def CheckIconFilesForLicenseHeaders(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506045 """Check that .icon files (which are fragments of C++) have license headers.
6046 """
Evan Stade6cfc964c12021-05-18 20:21:166047
Sam Maiera6e76d72022-02-11 21:43:506048 icon_files = (r'.*\.icon$', )
Evan Stade6cfc964c12021-05-18 20:21:166049
Sam Maiera6e76d72022-02-11 21:43:506050 icons = lambda x: input_api.FilterSourceFile(x, files_to_check=icon_files)
6051 return input_api.canned_checks.CheckLicense(input_api,
6052 output_api,
6053 source_file_filter=icons)
6054
Evan Stade6cfc964c12021-05-18 20:21:166055
Jose Magana2b456f22021-03-09 23:26:406056def CheckForUseOfChromeAppsDeprecations(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506057 """Check source code for use of Chrome App technologies being
6058 deprecated.
6059 """
Jose Magana2b456f22021-03-09 23:26:406060
Sam Maiera6e76d72022-02-11 21:43:506061 def _CheckForDeprecatedTech(input_api,
6062 output_api,
6063 detection_list,
6064 files_to_check=None,
6065 files_to_skip=None):
Jose Magana2b456f22021-03-09 23:26:406066
Sam Maiera6e76d72022-02-11 21:43:506067 if (files_to_check or files_to_skip):
6068 source_file_filter = lambda f: input_api.FilterSourceFile(
6069 f, files_to_check=files_to_check, files_to_skip=files_to_skip)
6070 else:
6071 source_file_filter = None
6072
6073 problems = []
6074
6075 for f in input_api.AffectedSourceFiles(source_file_filter):
6076 if f.Action() == 'D':
6077 continue
6078 for _, line in f.ChangedContents():
6079 if any(detect in line for detect in detection_list):
6080 problems.append(f.LocalPath())
6081
6082 return problems
6083
6084 # to avoid this presubmit script triggering warnings
6085 files_to_skip = ['PRESUBMIT.py', 'PRESUBMIT_test.py']
Jose Magana2b456f22021-03-09 23:26:406086
6087 problems = []
6088
Sam Maiera6e76d72022-02-11 21:43:506089 # NMF: any files with extensions .nmf or NMF
6090 _NMF_FILES = r'\.(nmf|NMF)$'
6091 problems += _CheckForDeprecatedTech(
6092 input_api,
6093 output_api,
6094 detection_list=[''], # any change to the file will trigger warning
6095 files_to_check=[r'.+%s' % _NMF_FILES])
Jose Magana2b456f22021-03-09 23:26:406096
Sam Maiera6e76d72022-02-11 21:43:506097 # MANIFEST: any manifest.json that in its diff includes "app":
6098 _MANIFEST_FILES = r'(manifest\.json)$'
6099 problems += _CheckForDeprecatedTech(
6100 input_api,
6101 output_api,
6102 detection_list=['"app":'],
6103 files_to_check=[r'.*%s' % _MANIFEST_FILES])
Jose Magana2b456f22021-03-09 23:26:406104
Sam Maiera6e76d72022-02-11 21:43:506105 # NaCl / PNaCl: any file that in its diff contains the strings in the list
6106 problems += _CheckForDeprecatedTech(
6107 input_api,
6108 output_api,
6109 detection_list=['config=nacl', 'enable-nacl', 'cpu=pnacl', 'nacl_io'],
Bruce Dawson40fece62022-09-16 19:58:316110 files_to_skip=files_to_skip + [r"^native_client_sdk/"])
Jose Magana2b456f22021-03-09 23:26:406111
Gao Shenga79ebd42022-08-08 17:25:596112 # PPAPI: any C/C++ file that in its diff includes a ppapi library
Sam Maiera6e76d72022-02-11 21:43:506113 problems += _CheckForDeprecatedTech(
6114 input_api,
6115 output_api,
6116 detection_list=['#include "ppapi', '#include <ppapi'],
6117 files_to_check=(r'.+%s' % _HEADER_EXTENSIONS,
6118 r'.+%s' % _IMPLEMENTATION_EXTENSIONS),
Bruce Dawson40fece62022-09-16 19:58:316119 files_to_skip=[r"^ppapi/"])
Jose Magana2b456f22021-03-09 23:26:406120
Sam Maiera6e76d72022-02-11 21:43:506121 if problems:
6122 return [
6123 output_api.PresubmitPromptWarning(
6124 'You are adding/modifying code'
6125 'related to technologies which will soon be deprecated (Chrome Apps, NaCl,'
6126 ' PNaCl, PPAPI). See this blog post for more details:\n'
6127 'https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html\n'
6128 'and this documentation for options to replace these technologies:\n'
6129 'https://developer.chrome.com/docs/apps/migration/\n' +
6130 '\n'.join(problems))
6131 ]
Jose Magana2b456f22021-03-09 23:26:406132
Sam Maiera6e76d72022-02-11 21:43:506133 return []
Jose Magana2b456f22021-03-09 23:26:406134
mostynbb639aca52015-01-07 20:31:236135
Saagar Sanghavifceeaae2020-08-12 16:40:366136def CheckSyslogUseWarningOnUpload(input_api, output_api, src_file_filter=None):
Sam Maiera6e76d72022-02-11 21:43:506137 """Checks that all source files use SYSLOG properly."""
6138 syslog_files = []
6139 for f in input_api.AffectedSourceFiles(src_file_filter):
6140 for line_number, line in f.ChangedContents():
6141 if 'SYSLOG' in line:
6142 syslog_files.append(f.LocalPath() + ':' + str(line_number))
pastarmovj032ba5bc2017-01-12 10:41:566143
Sam Maiera6e76d72022-02-11 21:43:506144 if syslog_files:
6145 return [
6146 output_api.PresubmitPromptWarning(
6147 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
6148 ' calls.\nFiles to check:\n',
6149 items=syslog_files)
6150 ]
6151 return []
pastarmovj89f7ee12016-09-20 14:58:136152
6153
[email protected]1f7b4172010-01-28 01:17:346154def CheckChangeOnUpload(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506155 if input_api.version < [2, 0, 0]:
6156 return [
6157 output_api.PresubmitError(
6158 "Your depot_tools is out of date. "
6159 "This PRESUBMIT.py requires at least presubmit_support version 2.0.0, "
6160 "but your version is %d.%d.%d" % tuple(input_api.version))
6161 ]
6162 results = []
6163 results.extend(
6164 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
6165 return results
[email protected]ca8d1982009-02-19 16:33:126166
6167
6168def CheckChangeOnCommit(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506169 if input_api.version < [2, 0, 0]:
6170 return [
6171 output_api.PresubmitError(
6172 "Your depot_tools is out of date. "
6173 "This PRESUBMIT.py requires at least presubmit_support version 2.0.0, "
6174 "but your version is %d.%d.%d" % tuple(input_api.version))
6175 ]
Saagar Sanghavifceeaae2020-08-12 16:40:366176
Sam Maiera6e76d72022-02-11 21:43:506177 results = []
6178 # Make sure the tree is 'open'.
6179 results.extend(
6180 input_api.canned_checks.CheckTreeIsOpen(
6181 input_api,
6182 output_api,
6183 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:276184
Sam Maiera6e76d72022-02-11 21:43:506185 results.extend(
6186 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
6187 results.extend(
6188 input_api.canned_checks.CheckChangeHasBugField(input_api, output_api))
6189 results.extend(
6190 input_api.canned_checks.CheckChangeHasNoUnwantedTags(
6191 input_api, output_api))
Sam Maiera6e76d72022-02-11 21:43:506192 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146193
6194
Saagar Sanghavifceeaae2020-08-12 16:40:366195def CheckStrings(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506196 """Check string ICU syntax validity and if translation screenshots exist."""
6197 # Skip translation screenshots check if a SkipTranslationScreenshotsCheck
6198 # footer is set to true.
6199 git_footers = input_api.change.GitFootersFromDescription()
6200 skip_screenshot_check_footer = [
6201 footer.lower() for footer in git_footers.get(
6202 u'Skip-Translation-Screenshots-Check', [])
6203 ]
6204 run_screenshot_check = u'true' not in skip_screenshot_check_footer
Edward Lesmesf7c5c6d2020-05-14 23:30:026205
Sam Maiera6e76d72022-02-11 21:43:506206 import os
6207 import re
6208 import sys
6209 from io import StringIO
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146210
Sam Maiera6e76d72022-02-11 21:43:506211 new_or_added_paths = set(f.LocalPath() for f in input_api.AffectedFiles()
6212 if (f.Action() == 'A' or f.Action() == 'M'))
6213 removed_paths = set(f.LocalPath()
6214 for f in input_api.AffectedFiles(include_deletes=True)
6215 if f.Action() == 'D')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146216
Sam Maiera6e76d72022-02-11 21:43:506217 affected_grds = [
6218 f for f in input_api.AffectedFiles()
6219 if f.LocalPath().endswith(('.grd', '.grdp'))
6220 ]
6221 affected_grds = [
6222 f for f in affected_grds if not 'testdata' in f.LocalPath()
6223 ]
6224 if not affected_grds:
6225 return []
meacer8c0d3832019-12-26 21:46:166226
Sam Maiera6e76d72022-02-11 21:43:506227 affected_png_paths = [
6228 f.AbsoluteLocalPath() for f in input_api.AffectedFiles()
6229 if (f.LocalPath().endswith('.png'))
6230 ]
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146231
Sam Maiera6e76d72022-02-11 21:43:506232 # Check for screenshots. Developers can upload screenshots using
6233 # tools/translation/upload_screenshots.py which finds and uploads
6234 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
6235 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
6236 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
6237 #
6238 # The logic here is as follows:
6239 #
6240 # - If the CL has a .png file under the screenshots directory for a grd
6241 # file, warn the developer. Actual images should never be checked into the
6242 # Chrome repo.
6243 #
6244 # - If the CL contains modified or new messages in grd files and doesn't
6245 # contain the corresponding .sha1 files, warn the developer to add images
6246 # and upload them via tools/translation/upload_screenshots.py.
6247 #
6248 # - If the CL contains modified or new messages in grd files and the
6249 # corresponding .sha1 files, everything looks good.
6250 #
6251 # - If the CL contains removed messages in grd files but the corresponding
6252 # .sha1 files aren't removed, warn the developer to remove them.
6253 unnecessary_screenshots = []
Jens Mueller054652c2023-05-10 15:12:306254 invalid_sha1 = []
Sam Maiera6e76d72022-02-11 21:43:506255 missing_sha1 = []
Bruce Dawson55776c42022-12-09 17:23:476256 missing_sha1_modified = []
Sam Maiera6e76d72022-02-11 21:43:506257 unnecessary_sha1_files = []
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146258
Sam Maiera6e76d72022-02-11 21:43:506259 # This checks verifies that the ICU syntax of messages this CL touched is
6260 # valid, and reports any found syntax errors.
6261 # Without this presubmit check, ICU syntax errors in Chromium strings can land
6262 # without developers being aware of them. Later on, such ICU syntax errors
6263 # break message extraction for translation, hence would block Chromium
6264 # translations until they are fixed.
6265 icu_syntax_errors = []
Jens Mueller054652c2023-05-10 15:12:306266 sha1_pattern = input_api.re.compile(r'^[a-fA-F0-9]{40}$',
6267 input_api.re.MULTILINE)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146268
Sam Maiera6e76d72022-02-11 21:43:506269 def _CheckScreenshotAdded(screenshots_dir, message_id):
6270 sha1_path = input_api.os_path.join(screenshots_dir,
6271 message_id + '.png.sha1')
6272 if sha1_path not in new_or_added_paths:
6273 missing_sha1.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:306274 elif not _CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:256275 invalid_sha1.append(sha1_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146276
Bruce Dawson55776c42022-12-09 17:23:476277 def _CheckScreenshotModified(screenshots_dir, message_id):
6278 sha1_path = input_api.os_path.join(screenshots_dir,
6279 message_id + '.png.sha1')
6280 if sha1_path not in new_or_added_paths:
6281 missing_sha1_modified.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:306282 elif not _CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:256283 invalid_sha1.append(sha1_path)
Jens Mueller054652c2023-05-10 15:12:306284
6285 def _CheckValidSha1(sha1_path):
Sam Maierb926c58c2023-08-08 19:58:256286 return sha1_pattern.search(
6287 next("\n".join(f.NewContents()) for f in input_api.AffectedFiles()
6288 if f.LocalPath() == sha1_path))
Bruce Dawson55776c42022-12-09 17:23:476289
Sam Maiera6e76d72022-02-11 21:43:506290 def _CheckScreenshotRemoved(screenshots_dir, message_id):
6291 sha1_path = input_api.os_path.join(screenshots_dir,
6292 message_id + '.png.sha1')
6293 if input_api.os_path.exists(
6294 sha1_path) and sha1_path not in removed_paths:
6295 unnecessary_sha1_files.append(sha1_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146296
Sam Maiera6e76d72022-02-11 21:43:506297 def _ValidateIcuSyntax(text, level, signatures):
6298 """Validates ICU syntax of a text string.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146299
Sam Maiera6e76d72022-02-11 21:43:506300 Check if text looks similar to ICU and checks for ICU syntax correctness
6301 in this case. Reports various issues with ICU syntax and values of
6302 variants. Supports checking of nested messages. Accumulate information of
6303 each ICU messages found in the text for further checking.
Rainhard Findlingfc31844c52020-05-15 09:58:266304
Sam Maiera6e76d72022-02-11 21:43:506305 Args:
6306 text: a string to check.
6307 level: a number of current nesting level.
6308 signatures: an accumulator, a list of tuple of (level, variable,
6309 kind, variants).
Rainhard Findlingfc31844c52020-05-15 09:58:266310
Sam Maiera6e76d72022-02-11 21:43:506311 Returns:
6312 None if a string is not ICU or no issue detected.
6313 A tuple of (message, start index, end index) if an issue detected.
6314 """
6315 valid_types = {
6316 'plural': (frozenset(
Rainhard Findling3cde3ef02024-02-05 18:40:326317 ['=0', '=1', '=2', '=3', 'zero', 'one', 'two', 'few', 'many',
Sam Maiera6e76d72022-02-11 21:43:506318 'other']), frozenset(['=1', 'other'])),
6319 'selectordinal': (frozenset(
Rainhard Findling3cde3ef02024-02-05 18:40:326320 ['=0', '=1', '=2', '=3', 'zero', 'one', 'two', 'few', 'many',
Sam Maiera6e76d72022-02-11 21:43:506321 'other']), frozenset(['one', 'other'])),
6322 'select': (frozenset(), frozenset(['other'])),
6323 }
Rainhard Findlingfc31844c52020-05-15 09:58:266324
Sam Maiera6e76d72022-02-11 21:43:506325 # Check if the message looks like an attempt to use ICU
6326 # plural. If yes - check if its syntax strictly matches ICU format.
6327 like = re.match(r'^[^{]*\{[^{]*\b(plural|selectordinal|select)\b',
6328 text)
6329 if not like:
6330 signatures.append((level, None, None, None))
6331 return
Rainhard Findlingfc31844c52020-05-15 09:58:266332
Sam Maiera6e76d72022-02-11 21:43:506333 # Check for valid prefix and suffix
6334 m = re.match(
6335 r'^([^{]*\{)([a-zA-Z0-9_]+),\s*'
6336 r'(plural|selectordinal|select),\s*'
6337 r'(?:offset:\d+)?\s*(.*)', text, re.DOTALL)
6338 if not m:
6339 return (('This message looks like an ICU plural, '
6340 'but does not follow ICU syntax.'), like.start(),
6341 like.end())
6342 starting, variable, kind, variant_pairs = m.groups()
6343 variants, depth, last_pos = _ParseIcuVariants(variant_pairs,
6344 m.start(4))
6345 if depth:
6346 return ('Invalid ICU format. Unbalanced opening bracket', last_pos,
6347 len(text))
6348 first = text[0]
6349 ending = text[last_pos:]
6350 if not starting:
6351 return ('Invalid ICU format. No initial opening bracket',
6352 last_pos - 1, last_pos)
6353 if not ending or '}' not in ending:
6354 return ('Invalid ICU format. No final closing bracket',
6355 last_pos - 1, last_pos)
6356 elif first != '{':
6357 return ((
6358 'Invalid ICU format. Extra characters at the start of a complex '
6359 'message (go/icu-message-migration): "%s"') % starting, 0,
6360 len(starting))
6361 elif ending != '}':
6362 return ((
6363 'Invalid ICU format. Extra characters at the end of a complex '
6364 'message (go/icu-message-migration): "%s"') % ending,
6365 last_pos - 1, len(text) - 1)
6366 if kind not in valid_types:
6367 return (('Unknown ICU message type %s. '
6368 'Valid types are: plural, select, selectordinal') % kind,
6369 0, 0)
6370 known, required = valid_types[kind]
6371 defined_variants = set()
6372 for variant, variant_range, value, value_range in variants:
6373 start, end = variant_range
6374 if variant in defined_variants:
6375 return ('Variant "%s" is defined more than once' % variant,
6376 start, end)
6377 elif known and variant not in known:
6378 return ('Variant "%s" is not valid for %s message' %
6379 (variant, kind), start, end)
6380 defined_variants.add(variant)
6381 # Check for nested structure
6382 res = _ValidateIcuSyntax(value[1:-1], level + 1, signatures)
6383 if res:
6384 return (res[0], res[1] + value_range[0] + 1,
6385 res[2] + value_range[0] + 1)
6386 missing = required - defined_variants
6387 if missing:
6388 return ('Required variants missing: %s' % ', '.join(missing), 0,
6389 len(text))
6390 signatures.append((level, variable, kind, defined_variants))
Rainhard Findlingfc31844c52020-05-15 09:58:266391
Sam Maiera6e76d72022-02-11 21:43:506392 def _ParseIcuVariants(text, offset=0):
6393 """Parse variants part of ICU complex message.
Rainhard Findlingfc31844c52020-05-15 09:58:266394
Sam Maiera6e76d72022-02-11 21:43:506395 Builds a tuple of variant names and values, as well as
6396 their offsets in the input string.
Rainhard Findlingfc31844c52020-05-15 09:58:266397
Sam Maiera6e76d72022-02-11 21:43:506398 Args:
6399 text: a string to parse
6400 offset: additional offset to add to positions in the text to get correct
6401 position in the complete ICU string.
Rainhard Findlingfc31844c52020-05-15 09:58:266402
Sam Maiera6e76d72022-02-11 21:43:506403 Returns:
6404 List of tuples, each tuple consist of four fields: variant name,
6405 variant name span (tuple of two integers), variant value, value
6406 span (tuple of two integers).
6407 """
6408 depth, start, end = 0, -1, -1
6409 variants = []
6410 key = None
6411 for idx, char in enumerate(text):
6412 if char == '{':
6413 if not depth:
6414 start = idx
6415 chunk = text[end + 1:start]
6416 key = chunk.strip()
6417 pos = offset + end + 1 + chunk.find(key)
6418 span = (pos, pos + len(key))
6419 depth += 1
6420 elif char == '}':
6421 if not depth:
6422 return variants, depth, offset + idx
6423 depth -= 1
6424 if not depth:
6425 end = idx
6426 variants.append((key, span, text[start:end + 1],
6427 (offset + start, offset + end + 1)))
6428 return variants, depth, offset + end + 1
Rainhard Findlingfc31844c52020-05-15 09:58:266429
Sam Maiera6e76d72022-02-11 21:43:506430 try:
6431 old_sys_path = sys.path
6432 sys.path = sys.path + [
6433 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
6434 'translation')
6435 ]
6436 from helper import grd_helper
6437 finally:
6438 sys.path = old_sys_path
Rainhard Findlingfc31844c52020-05-15 09:58:266439
Sam Maiera6e76d72022-02-11 21:43:506440 for f in affected_grds:
6441 file_path = f.LocalPath()
6442 old_id_to_msg_map = {}
6443 new_id_to_msg_map = {}
6444 # Note that this code doesn't check if the file has been deleted. This is
6445 # OK because it only uses the old and new file contents and doesn't load
6446 # the file via its path.
6447 # It's also possible that a file's content refers to a renamed or deleted
6448 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
6449 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
6450 # .grdp files.
6451 if file_path.endswith('.grdp'):
6452 if f.OldContents():
6453 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
6454 '\n'.join(f.OldContents()))
6455 if f.NewContents():
6456 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
6457 '\n'.join(f.NewContents()))
6458 else:
6459 file_dir = input_api.os_path.dirname(file_path) or '.'
6460 if f.OldContents():
6461 old_id_to_msg_map = grd_helper.GetGrdMessages(
6462 StringIO('\n'.join(f.OldContents())), file_dir)
6463 if f.NewContents():
6464 new_id_to_msg_map = grd_helper.GetGrdMessages(
6465 StringIO('\n'.join(f.NewContents())), file_dir)
Rainhard Findlingfc31844c52020-05-15 09:58:266466
Sam Maiera6e76d72022-02-11 21:43:506467 grd_name, ext = input_api.os_path.splitext(
6468 input_api.os_path.basename(file_path))
6469 screenshots_dir = input_api.os_path.join(
6470 input_api.os_path.dirname(file_path),
6471 grd_name + ext.replace('.', '_'))
Rainhard Findlingfc31844c52020-05-15 09:58:266472
Sam Maiera6e76d72022-02-11 21:43:506473 # Compute added, removed and modified message IDs.
6474 old_ids = set(old_id_to_msg_map)
6475 new_ids = set(new_id_to_msg_map)
6476 added_ids = new_ids - old_ids
6477 removed_ids = old_ids - new_ids
6478 modified_ids = set([])
6479 for key in old_ids.intersection(new_ids):
6480 if (old_id_to_msg_map[key].ContentsAsXml('', True) !=
6481 new_id_to_msg_map[key].ContentsAsXml('', True)):
6482 # The message content itself changed. Require an updated screenshot.
6483 modified_ids.add(key)
6484 elif old_id_to_msg_map[key].attrs['meaning'] != \
6485 new_id_to_msg_map[key].attrs['meaning']:
Jens Mueller054652c2023-05-10 15:12:306486 # The message meaning changed. We later check for a screenshot.
6487 modified_ids.add(key)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146488
Sam Maiera6e76d72022-02-11 21:43:506489 if run_screenshot_check:
6490 # Check the screenshot directory for .png files. Warn if there is any.
6491 for png_path in affected_png_paths:
6492 if png_path.startswith(screenshots_dir):
6493 unnecessary_screenshots.append(png_path)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146494
Sam Maiera6e76d72022-02-11 21:43:506495 for added_id in added_ids:
6496 _CheckScreenshotAdded(screenshots_dir, added_id)
Rainhard Findlingd8d04372020-08-13 13:30:096497
Sam Maiera6e76d72022-02-11 21:43:506498 for modified_id in modified_ids:
Bruce Dawson55776c42022-12-09 17:23:476499 _CheckScreenshotModified(screenshots_dir, modified_id)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146500
Sam Maiera6e76d72022-02-11 21:43:506501 for removed_id in removed_ids:
6502 _CheckScreenshotRemoved(screenshots_dir, removed_id)
6503
6504 # Check new and changed strings for ICU syntax errors.
6505 for key in added_ids.union(modified_ids):
6506 msg = new_id_to_msg_map[key].ContentsAsXml('', True)
6507 err = _ValidateIcuSyntax(msg, 0, [])
6508 if err is not None:
6509 icu_syntax_errors.append(str(key) + ': ' + str(err[0]))
6510
6511 results = []
Rainhard Findlingfc31844c52020-05-15 09:58:266512 if run_screenshot_check:
Sam Maiera6e76d72022-02-11 21:43:506513 if unnecessary_screenshots:
6514 results.append(
6515 output_api.PresubmitError(
6516 'Do not include actual screenshots in the changelist. Run '
6517 'tools/translate/upload_screenshots.py to upload them instead:',
6518 sorted(unnecessary_screenshots)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146519
Sam Maiera6e76d72022-02-11 21:43:506520 if missing_sha1:
6521 results.append(
6522 output_api.PresubmitError(
Bruce Dawson55776c42022-12-09 17:23:476523 'You are adding UI strings.\n'
Sam Maiera6e76d72022-02-11 21:43:506524 'To ensure the best translations, take screenshots of the relevant UI '
6525 '(https://g.co/chrome/translation) and add these files to your '
6526 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146527
Jens Mueller054652c2023-05-10 15:12:306528 if invalid_sha1:
6529 results.append(
6530 output_api.PresubmitError(
6531 'The following files do not seem to contain valid sha1 hashes. '
6532 'Make sure they contain hashes created by '
6533 'tools/translate/upload_screenshots.py:', sorted(invalid_sha1)))
6534
Bruce Dawson55776c42022-12-09 17:23:476535 if missing_sha1_modified:
6536 results.append(
6537 output_api.PresubmitError(
6538 'You are modifying UI strings or their meanings.\n'
6539 'To ensure the best translations, take screenshots of the relevant UI '
6540 '(https://g.co/chrome/translation) and add these files to your '
6541 'changelist:', sorted(missing_sha1_modified)))
6542
Sam Maiera6e76d72022-02-11 21:43:506543 if unnecessary_sha1_files:
6544 results.append(
6545 output_api.PresubmitError(
6546 'You removed strings associated with these files. Remove:',
6547 sorted(unnecessary_sha1_files)))
6548 else:
6549 results.append(
6550 output_api.PresubmitPromptOrNotify('Skipping translation '
6551 'screenshots check.'))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:146552
Sam Maiera6e76d72022-02-11 21:43:506553 if icu_syntax_errors:
6554 results.append(
6555 output_api.PresubmitPromptWarning(
6556 'ICU syntax errors were found in the following strings (problems or '
6557 'feedback? Contact [email protected]):',
6558 items=icu_syntax_errors))
Rainhard Findlingfc31844c52020-05-15 09:58:266559
Sam Maiera6e76d72022-02-11 21:43:506560 return results
Mustafa Emre Acer51f2f742020-03-09 19:41:126561
6562
Saagar Sanghavifceeaae2020-08-12 16:40:366563def CheckTranslationExpectations(input_api, output_api,
Mustafa Emre Acer51f2f742020-03-09 19:41:126564 repo_root=None,
6565 translation_expectations_path=None,
6566 grd_files=None):
Sam Maiera6e76d72022-02-11 21:43:506567 import sys
6568 affected_grds = [
6569 f for f in input_api.AffectedFiles()
6570 if (f.LocalPath().endswith('.grd') or f.LocalPath().endswith('.grdp'))
6571 ]
6572 if not affected_grds:
6573 return []
6574
6575 try:
6576 old_sys_path = sys.path
6577 sys.path = sys.path + [
6578 input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools',
6579 'translation')
6580 ]
6581 from helper import git_helper
6582 from helper import translation_helper
6583 finally:
6584 sys.path = old_sys_path
6585
6586 # Check that translation expectations can be parsed and we can get a list of
6587 # translatable grd files. |repo_root| and |translation_expectations_path| are
6588 # only passed by tests.
6589 if not repo_root:
6590 repo_root = input_api.PresubmitLocalPath()
6591 if not translation_expectations_path:
6592 translation_expectations_path = input_api.os_path.join(
6593 repo_root, 'tools', 'gritsettings', 'translation_expectations.pyl')
6594 if not grd_files:
6595 grd_files = git_helper.list_grds_in_repository(repo_root)
6596
6597 # Ignore bogus grd files used only for testing
Gao Shenga79ebd42022-08-08 17:25:596598 # ui/webui/resources/tools/generate_grd.py.
Sam Maiera6e76d72022-02-11 21:43:506599 ignore_path = input_api.os_path.join('ui', 'webui', 'resources', 'tools',
6600 'tests')
6601 grd_files = [p for p in grd_files if ignore_path not in p]
6602
6603 try:
6604 translation_helper.get_translatable_grds(
6605 repo_root, grd_files, translation_expectations_path)
6606 except Exception as e:
6607 return [
6608 output_api.PresubmitNotifyResult(
6609 'Failed to get a list of translatable grd files. This happens when:\n'
6610 ' - One of the modified grd or grdp files cannot be parsed or\n'
6611 ' - %s is not updated.\n'
6612 'Stack:\n%s' % (translation_expectations_path, str(e)))
6613 ]
Mustafa Emre Acer51f2f742020-03-09 19:41:126614 return []
6615
Ken Rockotc31f4832020-05-29 18:58:516616
Saagar Sanghavifceeaae2020-08-12 16:40:366617def CheckStableMojomChanges(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506618 """Changes to [Stable] mojom types must preserve backward-compatibility."""
6619 changed_mojoms = input_api.AffectedFiles(
6620 include_deletes=True,
6621 file_filter=lambda f: f.LocalPath().endswith(('.mojom')))
Erik Staabc734cd7a2021-11-23 03:11:526622
Bruce Dawson344ab262022-06-04 11:35:106623 if not changed_mojoms or input_api.no_diffs:
Sam Maiera6e76d72022-02-11 21:43:506624 return []
6625
6626 delta = []
6627 for mojom in changed_mojoms:
Sam Maiera6e76d72022-02-11 21:43:506628 delta.append({
6629 'filename': mojom.LocalPath(),
6630 'old': '\n'.join(mojom.OldContents()) or None,
6631 'new': '\n'.join(mojom.NewContents()) or None,
6632 })
6633
6634 process = input_api.subprocess.Popen([
Takuto Ikutadca10222022-04-13 02:51:216635 input_api.python3_executable,
Sam Maiera6e76d72022-02-11 21:43:506636 input_api.os_path.join(
6637 input_api.PresubmitLocalPath(), 'mojo', 'public', 'tools', 'mojom',
6638 'check_stable_mojom_compatibility.py'), '--src-root',
6639 input_api.PresubmitLocalPath()
6640 ],
6641 stdin=input_api.subprocess.PIPE,
6642 stdout=input_api.subprocess.PIPE,
6643 stderr=input_api.subprocess.PIPE,
6644 universal_newlines=True)
6645 (x, error) = process.communicate(input=input_api.json.dumps(delta))
6646 if process.returncode:
6647 return [
6648 output_api.PresubmitError(
6649 'One or more [Stable] mojom definitions appears to have been changed '
Alex Goughc99921652024-02-15 22:59:126650 'in a way that is not backward-compatible. See '
6651 'https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/public/tools/bindings/README.md#versioning'
6652 ' for details.',
Sam Maiera6e76d72022-02-11 21:43:506653 long_text=error)
6654 ]
Erik Staabc734cd7a2021-11-23 03:11:526655 return []
6656
Dominic Battre645d42342020-12-04 16:14:106657def CheckDeprecationOfPreferences(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506658 """Removing a preference should come with a deprecation."""
Dominic Battre645d42342020-12-04 16:14:106659
Sam Maiera6e76d72022-02-11 21:43:506660 def FilterFile(affected_file):
6661 """Accept only .cc files and the like."""
6662 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
6663 files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
6664 input_api.DEFAULT_FILES_TO_SKIP)
6665 return input_api.FilterSourceFile(
6666 affected_file,
6667 files_to_check=file_inclusion_pattern,
6668 files_to_skip=files_to_skip)
Dominic Battre645d42342020-12-04 16:14:106669
Sam Maiera6e76d72022-02-11 21:43:506670 def ModifiedLines(affected_file):
6671 """Returns a list of tuples (line number, line text) of added and removed
6672 lines.
Dominic Battre645d42342020-12-04 16:14:106673
Sam Maiera6e76d72022-02-11 21:43:506674 Deleted lines share the same line number as the previous line.
Dominic Battre645d42342020-12-04 16:14:106675
Sam Maiera6e76d72022-02-11 21:43:506676 This relies on the scm diff output describing each changed code section
6677 with a line of the form
Dominic Battre645d42342020-12-04 16:14:106678
Sam Maiera6e76d72022-02-11 21:43:506679 ^@@ <old line num>,<old size> <new line num>,<new size> @@$
6680 """
6681 line_num = 0
6682 modified_lines = []
6683 for line in affected_file.GenerateScmDiff().splitlines():
6684 # Extract <new line num> of the patch fragment (see format above).
6685 m = input_api.re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@',
6686 line)
6687 if m:
6688 line_num = int(m.groups(1)[0])
6689 continue
6690 if ((line.startswith('+') and not line.startswith('++'))
6691 or (line.startswith('-') and not line.startswith('--'))):
6692 modified_lines.append((line_num, line))
Dominic Battre645d42342020-12-04 16:14:106693
Sam Maiera6e76d72022-02-11 21:43:506694 if not line.startswith('-'):
6695 line_num += 1
6696 return modified_lines
Dominic Battre645d42342020-12-04 16:14:106697
Sam Maiera6e76d72022-02-11 21:43:506698 def FindLineWith(lines, needle):
6699 """Returns the line number (i.e. index + 1) in `lines` containing `needle`.
Dominic Battre645d42342020-12-04 16:14:106700
Sam Maiera6e76d72022-02-11 21:43:506701 If 0 or >1 lines contain `needle`, -1 is returned.
6702 """
6703 matching_line_numbers = [
6704 # + 1 for 1-based counting of line numbers.
6705 i + 1 for i, line in enumerate(lines) if needle in line
6706 ]
6707 return matching_line_numbers[0] if len(
6708 matching_line_numbers) == 1 else -1
Dominic Battre645d42342020-12-04 16:14:106709
Sam Maiera6e76d72022-02-11 21:43:506710 def ModifiedPrefMigration(affected_file):
6711 """Returns whether the MigrateObsolete.*Pref functions were modified."""
6712 # Determine first and last lines of MigrateObsolete.*Pref functions.
6713 new_contents = affected_file.NewContents()
6714 range_1 = (FindLineWith(new_contents,
6715 'BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'),
6716 FindLineWith(new_contents,
6717 'END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'))
6718 range_2 = (FindLineWith(new_contents,
6719 'BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS'),
6720 FindLineWith(new_contents,
6721 'END_MIGRATE_OBSOLETE_PROFILE_PREFS'))
6722 if (-1 in range_1 + range_2):
6723 raise Exception(
6724 'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.'
6725 )
Dominic Battre645d42342020-12-04 16:14:106726
Sam Maiera6e76d72022-02-11 21:43:506727 # Check whether any of the modified lines are part of the
6728 # MigrateObsolete.*Pref functions.
6729 for line_nr, line in ModifiedLines(affected_file):
6730 if (range_1[0] <= line_nr <= range_1[1]
6731 or range_2[0] <= line_nr <= range_2[1]):
6732 return True
6733 return False
Dominic Battre645d42342020-12-04 16:14:106734
Sam Maiera6e76d72022-02-11 21:43:506735 register_pref_pattern = input_api.re.compile(r'Register.+Pref')
6736 browser_prefs_file_pattern = input_api.re.compile(
6737 r'chrome/browser/prefs/browser_prefs.cc')
Dominic Battre645d42342020-12-04 16:14:106738
Sam Maiera6e76d72022-02-11 21:43:506739 changes = input_api.AffectedFiles(include_deletes=True,
6740 file_filter=FilterFile)
6741 potential_problems = []
6742 for f in changes:
6743 for line in f.GenerateScmDiff().splitlines():
6744 # Check deleted lines for pref registrations.
6745 if (line.startswith('-') and not line.startswith('--')
6746 and register_pref_pattern.search(line)):
6747 potential_problems.append('%s: %s' % (f.LocalPath(), line))
Dominic Battre645d42342020-12-04 16:14:106748
Sam Maiera6e76d72022-02-11 21:43:506749 if browser_prefs_file_pattern.search(f.LocalPath()):
6750 # If the developer modified the MigrateObsolete.*Prefs() functions, we
6751 # assume that they knew that they have to deprecate preferences and don't
6752 # warn.
6753 try:
6754 if ModifiedPrefMigration(f):
6755 return []
6756 except Exception as e:
6757 return [output_api.PresubmitError(str(e))]
Dominic Battre645d42342020-12-04 16:14:106758
Sam Maiera6e76d72022-02-11 21:43:506759 if potential_problems:
6760 return [
6761 output_api.PresubmitPromptWarning(
6762 'Discovered possible removal of preference registrations.\n\n'
6763 'Please make sure to properly deprecate preferences by clearing their\n'
6764 'value for a couple of milestones before finally removing the code.\n'
6765 'Otherwise data may stay in the preferences files forever. See\n'
6766 'Migrate*Prefs() in chrome/browser/prefs/browser_prefs.cc and\n'
6767 'chrome/browser/prefs/README.md for examples.\n'
6768 'This may be a false positive warning (e.g. if you move preference\n'
6769 'registrations to a different place).\n', potential_problems)
6770 ]
6771 return []
6772
Matt Stark6ef08872021-07-29 01:21:466773
6774def CheckConsistentGrdChanges(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506775 """Changes to GRD files must be consistent for tools to read them."""
6776 changed_grds = input_api.AffectedFiles(
6777 include_deletes=False,
6778 file_filter=lambda f: f.LocalPath().endswith(('.grd')))
6779 errors = []
6780 invalid_file_regexes = [(input_api.re.compile(matcher), msg)
6781 for matcher, msg in _INVALID_GRD_FILE_LINE]
6782 for grd in changed_grds:
6783 for i, line in enumerate(grd.NewContents()):
6784 for matcher, msg in invalid_file_regexes:
6785 if matcher.search(line):
6786 errors.append(
6787 output_api.PresubmitError(
6788 'Problem on {grd}:{i} - {msg}'.format(
6789 grd=grd.LocalPath(), i=i + 1, msg=msg)))
6790 return errors
6791
Kevin McNee967dd2d22021-11-15 16:09:296792
Henrique Ferreiro2a4b55942021-11-29 23:45:366793def CheckAssertAshOnlyCode(input_api, output_api):
6794 """Errors if a BUILD.gn file in an ash/ directory doesn't include
6795 assert(is_chromeos_ash).
6796 """
6797
6798 def FileFilter(affected_file):
6799 """Includes directories known to be Ash only."""
6800 return input_api.FilterSourceFile(
6801 affected_file,
6802 files_to_check=(
6803 r'^ash/.*BUILD\.gn', # Top-level src/ash/.
6804 r'.*/ash/.*BUILD\.gn'), # Any path component.
6805 files_to_skip=(input_api.DEFAULT_FILES_TO_SKIP))
6806
6807 errors = []
6808 pattern = input_api.re.compile(r'assert\(is_chromeos_ash')
Jameson Thies0ce669f2021-12-09 15:56:566809 for f in input_api.AffectedFiles(include_deletes=False,
6810 file_filter=FileFilter):
Henrique Ferreiro2a4b55942021-11-29 23:45:366811 if (not pattern.search(input_api.ReadFile(f))):
6812 errors.append(
6813 output_api.PresubmitError(
6814 'Please add assert(is_chromeos_ash) to %s. If that\'s not '
6815 'possible, please create and issue and add a comment such '
6816 'as:\n # TODO(https://crbug.com/XXX): add '
6817 'assert(is_chromeos_ash) when ...' % f.LocalPath()))
6818 return errors
Lukasz Anforowicz7016d05e2021-11-30 03:56:276819
6820
Kalvin Lee84ad17a2023-09-25 11:14:416821def _IsMiraclePtrDisallowed(input_api, affected_file):
Sam Maiera6e76d72022-02-11 21:43:506822 path = affected_file.LocalPath()
6823 if not _IsCPlusPlusFile(input_api, path):
6824 return False
6825
Kalvin Lee84ad17a2023-09-25 11:14:416826 # Renderer code is generally allowed to use MiraclePtr.
6827 # These directories, however, are specifically disallowed.
6828 if ("third_party/blink/renderer/core/" in path
6829 or "third_party/blink/renderer/platform/heap/" in path
6830 or "third_party/blink/renderer/platform/wtf/" in path):
Sam Maiera6e76d72022-02-11 21:43:506831 return True
6832
6833 # Blink's public/web API is only used/included by Renderer-only code. Note
6834 # that public/platform API may be used in non-Renderer processes (e.g. there
6835 # are some includes in code used by Utility, PDF, or Plugin processes).
6836 if "/blink/public/web/" in path:
6837 return True
6838
6839 # We assume that everything else may be used outside of Renderer processes.
Lukasz Anforowicz7016d05e2021-11-30 03:56:276840 return False
6841
Lukasz Anforowicz7016d05e2021-11-30 03:56:276842# TODO(https://crbug.com/1273182): Remove these checks, once they are replaced
6843# by the Chromium Clang Plugin (which will be preferable because it will
6844# 1) report errors earlier - at compile-time and 2) cover more rules).
6845def CheckRawPtrUsage(input_api, output_api):
Sam Maiera6e76d72022-02-11 21:43:506846 """Rough checks that raw_ptr<T> usage guidelines are followed."""
6847 errors = []
6848 # The regex below matches "raw_ptr<" following a word boundary, but not in a
6849 # C++ comment.
6850 raw_ptr_matcher = input_api.re.compile(r'^((?!//).)*\braw_ptr<')
Kalvin Lee84ad17a2023-09-25 11:14:416851 file_filter = lambda f: _IsMiraclePtrDisallowed(input_api, f)
Sam Maiera6e76d72022-02-11 21:43:506852 for f, line_num, line in input_api.RightHandSideLines(file_filter):
6853 if raw_ptr_matcher.search(line):
6854 errors.append(
6855 output_api.PresubmitError(
6856 'Problem on {path}:{line} - '\
Kalvin Lee84ad17a2023-09-25 11:14:416857 'raw_ptr<T> should not be used in this renderer code '\
Sam Maiera6e76d72022-02-11 21:43:506858 '(as documented in the "Pointers to unprotected memory" '\
6859 'section in //base/memory/raw_ptr.md)'.format(
6860 path=f.LocalPath(), line=line_num)))
6861 return errors
Henrique Ferreirof9819f2e32021-11-30 13:31:566862
mikt9337567c2023-09-08 18:38:176863def CheckAdvancedMemorySafetyChecksUsage(input_api, output_api):
6864 """Checks that ADVANCED_MEMORY_SAFETY_CHECKS() macro is neither added nor
6865 removed as it is managed by the memory safety team internally.
6866 Do not add / remove it manually."""
6867 paths = set([])
6868 # The regex below matches "ADVANCED_MEMORY_SAFETY_CHECKS(" following a word
6869 # boundary, but not in a C++ comment.
6870 macro_matcher = input_api.re.compile(
6871 r'^((?!//).)*\bADVANCED_MEMORY_SAFETY_CHECKS\(', input_api.re.MULTILINE)
6872 for f in input_api.AffectedFiles():
6873 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
6874 continue
6875 if macro_matcher.search(f.GenerateScmDiff()):
6876 paths.add(f.LocalPath())
6877 if not paths:
6878 return []
6879 return [output_api.PresubmitPromptWarning(
6880 'ADVANCED_MEMORY_SAFETY_CHECKS() macro is managed by ' \
6881 'the memory safety team (chrome-memory-safety@). ' \
6882 'Please contact us to add/delete the uses of the macro.',
6883 paths)]
Henrique Ferreirof9819f2e32021-11-30 13:31:566884
6885def CheckPythonShebang(input_api, output_api):
6886 """Checks that python scripts use #!/usr/bin/env instead of hardcoding a
6887 system-wide python.
6888 """
6889 errors = []
6890 sources = lambda affected_file: input_api.FilterSourceFile(
6891 affected_file,
6892 files_to_skip=((_THIRD_PARTY_EXCEPT_BLINK,
6893 r'third_party/blink/web_tests/external/') + input_api.
6894 DEFAULT_FILES_TO_SKIP),
6895 files_to_check=[r'.*\.py$'])
6896 for f in input_api.AffectedSourceFiles(sources):
Takuto Ikuta36976512021-11-30 23:15:276897 for line_num, line in f.ChangedContents():
6898 if line_num == 1 and line.startswith('#!/usr/bin/python'):
6899 errors.append(f.LocalPath())
6900 break
Henrique Ferreirof9819f2e32021-11-30 13:31:566901
6902 result = []
6903 for file in errors:
6904 result.append(
6905 output_api.PresubmitError(
6906 "Please use '#!/usr/bin/env python/2/3' as the shebang of %s" %
6907 file))
6908 return result
James Shen81cc0e22022-06-15 21:10:456909
6910
6911def CheckBatchAnnotation(input_api, output_api):
6912 """Checks that tests have either @Batch or @DoNotBatch annotation. If this
6913 is not an instrumentation test, disregard."""
6914
6915 batch_annotation = input_api.re.compile(r'^\s*@Batch')
6916 do_not_batch_annotation = input_api.re.compile(r'^\s*@DoNotBatch')
6917 robolectric_test = input_api.re.compile(r'[rR]obolectric')
6918 test_class_declaration = input_api.re.compile(r'^\s*public\sclass.*Test')
6919 uiautomator_test = input_api.re.compile(r'[uU]i[aA]utomator')
Mark Schillaci8ef0d872023-07-18 22:07:596920 test_annotation_declaration = input_api.re.compile(r'^\s*public\s@interface\s.*{')
James Shen81cc0e22022-06-15 21:10:456921
ckitagawae8fd23b2022-06-17 15:29:386922 missing_annotation_errors = []
6923 extra_annotation_errors = []
James Shen81cc0e22022-06-15 21:10:456924
6925 def _FilterFile(affected_file):
6926 return input_api.FilterSourceFile(
6927 affected_file,
6928 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP,
6929 files_to_check=[r'.*Test\.java$'])
6930
6931 for f in input_api.AffectedSourceFiles(_FilterFile):
6932 batch_matched = None
6933 do_not_batch_matched = None
6934 is_instrumentation_test = True
Mark Schillaci8ef0d872023-07-18 22:07:596935 test_annotation_declaration_matched = None
James Shen81cc0e22022-06-15 21:10:456936 for line in f.NewContents():
6937 if robolectric_test.search(line) or uiautomator_test.search(line):
6938 # Skip Robolectric and UiAutomator tests.
6939 is_instrumentation_test = False
6940 break
6941 if not batch_matched:
6942 batch_matched = batch_annotation.search(line)
6943 if not do_not_batch_matched:
6944 do_not_batch_matched = do_not_batch_annotation.search(line)
6945 test_class_declaration_matched = test_class_declaration.search(
6946 line)
Mark Schillaci8ef0d872023-07-18 22:07:596947 test_annotation_declaration_matched = test_annotation_declaration.search(line)
6948 if test_class_declaration_matched or test_annotation_declaration_matched:
James Shen81cc0e22022-06-15 21:10:456949 break
Mark Schillaci8ef0d872023-07-18 22:07:596950 if test_annotation_declaration_matched:
6951 continue
James Shen81cc0e22022-06-15 21:10:456952 if (is_instrumentation_test and
6953 not batch_matched and
6954 not do_not_batch_matched):
Sam Maier4cef9242022-10-03 14:21:246955 missing_annotation_errors.append(str(f.LocalPath()))
ckitagawae8fd23b2022-06-17 15:29:386956 if (not is_instrumentation_test and
6957 (batch_matched or
6958 do_not_batch_matched)):
Sam Maier4cef9242022-10-03 14:21:246959 extra_annotation_errors.append(str(f.LocalPath()))
James Shen81cc0e22022-06-15 21:10:456960
6961 results = []
6962
ckitagawae8fd23b2022-06-17 15:29:386963 if missing_annotation_errors:
James Shen81cc0e22022-06-15 21:10:456964 results.append(
6965 output_api.PresubmitPromptWarning(
6966 """
Andrew Grieve43a5cf82023-09-08 15:09:466967A change was made to an on-device test that has neither been annotated with
6968@Batch nor @DoNotBatch. If this is a new test, please add the annotation. If
6969this is an existing test, please consider adding it if you are sufficiently
6970familiar with the test (but do so as a separate change).
6971
Jens Mueller2085ff82023-02-27 11:54:496972See https://source.chromium.org/chromium/chromium/src/+/main:docs/testing/batching_instrumentation_tests.md
ckitagawae8fd23b2022-06-17 15:29:386973""", missing_annotation_errors))
6974 if extra_annotation_errors:
6975 results.append(
6976 output_api.PresubmitPromptWarning(
6977 """
6978Robolectric tests do not need a @Batch or @DoNotBatch annotations.
6979""", extra_annotation_errors))
James Shen81cc0e22022-06-15 21:10:456980
6981 return results
Sam Maier4cef9242022-10-03 14:21:246982
6983
6984def CheckMockAnnotation(input_api, output_api):
6985 """Checks that we have annotated all Mockito.mock()-ed or Mockito.spy()-ed
6986 classes with @Mock or @Spy. If this is not an instrumentation test,
6987 disregard."""
6988
6989 # This is just trying to be approximately correct. We are not writing a
6990 # Java parser, so special cases like statically importing mock() then
6991 # calling an unrelated non-mockito spy() function will cause a false
6992 # positive.
6993 package_name = input_api.re.compile(r'^package\s+(\w+(?:\.\w+)+);')
6994 mock_static_import = input_api.re.compile(
6995 r'^import\s+static\s+org.mockito.Mockito.(?:mock|spy);')
6996 import_class = input_api.re.compile(r'import\s+((?:\w+\.)+)(\w+);')
6997 mock_annotation = input_api.re.compile(r'^\s*@(?:Mock|Spy)')
6998 field_type = input_api.re.compile(r'(\w+)(?:<\w+>)?\s+\w+\s*(?:;|=)')
6999 mock_or_spy_function_call = r'(?:mock|spy)\(\s*(?:new\s*)?(\w+)(?:\.class|\()'
7000 fully_qualified_mock_function = input_api.re.compile(
7001 r'Mockito\.' + mock_or_spy_function_call)
7002 statically_imported_mock_function = input_api.re.compile(
7003 r'\W' + mock_or_spy_function_call)
7004 robolectric_test = input_api.re.compile(r'[rR]obolectric')
7005 uiautomator_test = input_api.re.compile(r'[uU]i[aA]utomator')
7006
7007 def _DoClassLookup(class_name, class_name_map, package):
7008 found = class_name_map.get(class_name)
7009 if found is not None:
7010 return found
7011 else:
7012 return package + '.' + class_name
7013
7014 def _FilterFile(affected_file):
7015 return input_api.FilterSourceFile(
7016 affected_file,
7017 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP,
7018 files_to_check=[r'.*Test\.java$'])
7019
7020 mocked_by_function_classes = set()
7021 mocked_by_annotation_classes = set()
7022 class_to_filename = {}
7023 for f in input_api.AffectedSourceFiles(_FilterFile):
7024 mock_function_regex = fully_qualified_mock_function
7025 next_line_is_annotated = False
7026 fully_qualified_class_map = {}
7027 package = None
7028
7029 for line in f.NewContents():
7030 if robolectric_test.search(line) or uiautomator_test.search(line):
7031 # Skip Robolectric and UiAutomator tests.
7032 break
7033
7034 m = package_name.search(line)
7035 if m:
7036 package = m.group(1)
7037 continue
7038
7039 if mock_static_import.search(line):
7040 mock_function_regex = statically_imported_mock_function
7041 continue
7042
7043 m = import_class.search(line)
7044 if m:
7045 fully_qualified_class_map[m.group(2)] = m.group(1) + m.group(2)
7046 continue
7047
7048 if next_line_is_annotated:
7049 next_line_is_annotated = False
7050 fully_qualified_class = _DoClassLookup(
7051 field_type.search(line).group(1), fully_qualified_class_map,
7052 package)
7053 mocked_by_annotation_classes.add(fully_qualified_class)
7054 continue
7055
7056 if mock_annotation.search(line):
Sam Maierb8a66a02023-10-10 13:50:557057 field_type_search = field_type.search(line)
7058 if field_type_search:
7059 fully_qualified_class = _DoClassLookup(
7060 field_type_search.group(1), fully_qualified_class_map,
7061 package)
7062 mocked_by_annotation_classes.add(fully_qualified_class)
7063 else:
7064 next_line_is_annotated = True
Sam Maier4cef9242022-10-03 14:21:247065 continue
7066
7067 m = mock_function_regex.search(line)
7068 if m:
7069 fully_qualified_class = _DoClassLookup(m.group(1),
7070 fully_qualified_class_map, package)
7071 # Skipping builtin classes, since they don't get optimized.
7072 if fully_qualified_class.startswith(
7073 'android.') or fully_qualified_class.startswith(
7074 'java.'):
7075 continue
7076 class_to_filename[fully_qualified_class] = str(f.LocalPath())
7077 mocked_by_function_classes.add(fully_qualified_class)
7078
7079 results = []
7080 missed_classes = mocked_by_function_classes - mocked_by_annotation_classes
7081 if missed_classes:
7082 error_locations = []
7083 for c in missed_classes:
7084 error_locations.append(c + ' in ' + class_to_filename[c])
7085 results.append(
7086 output_api.PresubmitPromptWarning(
7087 """
7088Mockito.mock()/spy() cause issues with our Java optimizer. You have 3 options:
70891) If the mocked variable can be a class member, annotate the member with
7090 @Mock/@Spy.
70912) If the mocked variable cannot be a class member, create a dummy member
7092 variable of that type, annotated with @Mock/@Spy. This dummy does not need
7093 to be used or initialized in any way.
70943) If the mocked type is definitely not going to be optimized, whether it's a
7095 builtin type which we don't ship, or a class you know R8 will treat
7096 specially, you can ignore this warning.
7097""", error_locations))
7098
7099 return results
Mike Dougherty1b8be712022-10-20 00:15:137100
7101def CheckNoJsInIos(input_api, output_api):
7102 """Checks to make sure that JavaScript files are not used on iOS."""
7103
7104 def _FilterFile(affected_file):
7105 return input_api.FilterSourceFile(
7106 affected_file,
7107 files_to_skip=input_api.DEFAULT_FILES_TO_SKIP +
Daniel White44b8bd02023-08-22 16:20:367108 (r'^ios/third_party/*', r'^ios/tools/*', r'^third_party/*',
7109 r'^components/autofill/ios/form_util/resources/*'),
Mike Dougherty1b8be712022-10-20 00:15:137110 files_to_check=[r'^ios/.*\.js$', r'.*/ios/.*\.js$'])
7111
Mike Dougherty4d1050b2023-03-14 15:59:537112 deleted_files = []
7113
7114 # Collect filenames of all removed JS files.
7115 for f in input_api.AffectedSourceFiles(_FilterFile):
7116 local_path = f.LocalPath()
7117
7118 if input_api.os_path.splitext(local_path)[1] == '.js' and f.Action() == 'D':
7119 deleted_files.append(input_api.os_path.basename(local_path))
7120
Mike Dougherty1b8be712022-10-20 00:15:137121 error_paths = []
Mike Dougherty4d1050b2023-03-14 15:59:537122 moved_paths = []
Mike Dougherty1b8be712022-10-20 00:15:137123 warning_paths = []
7124
7125 for f in input_api.AffectedSourceFiles(_FilterFile):
7126 local_path = f.LocalPath()
7127
7128 if input_api.os_path.splitext(local_path)[1] == '.js':
7129 if f.Action() == 'A':
Mike Dougherty4d1050b2023-03-14 15:59:537130 if input_api.os_path.basename(local_path) in deleted_files:
7131 # This script was probably moved rather than newly created.
7132 # Present a warning instead of an error for these cases.
7133 moved_paths.append(local_path)
7134 else:
7135 error_paths.append(local_path)
Mike Dougherty1b8be712022-10-20 00:15:137136 elif f.Action() != 'D':
7137 warning_paths.append(local_path)
7138
7139 results = []
7140
7141 if warning_paths:
7142 results.append(output_api.PresubmitPromptWarning(
7143 'TypeScript is now fully supported for iOS feature scripts. '
7144 'Consider converting JavaScript files to TypeScript. See '
7145 '//ios/web/public/js_messaging/README.md for more details.',
7146 warning_paths))
7147
Mike Dougherty4d1050b2023-03-14 15:59:537148 if moved_paths:
7149 results.append(output_api.PresubmitPromptWarning(
7150 'Do not use JavaScript on iOS for new files as TypeScript is '
7151 'fully supported. (If this is a moved file, you may leave the '
7152 'script unconverted.) See //ios/web/public/js_messaging/README.md '
7153 'for help using scripts on iOS.', moved_paths))
7154
Mike Dougherty1b8be712022-10-20 00:15:137155 if error_paths:
7156 results.append(output_api.PresubmitError(
7157 'Do not use JavaScript on iOS as TypeScript is fully supported. '
7158 'See //ios/web/public/js_messaging/README.md for help using '
7159 'scripts on iOS.', error_paths))
7160
7161 return results
Hans Wennborg23a81d52023-03-24 16:38:137162
7163def CheckLibcxxRevisionsMatch(input_api, output_api):
7164 """Check to make sure the libc++ version matches across deps files."""
Andrew Grieve21bb6792023-03-27 19:06:487165 # Disable check for changes to sub-repositories.
7166 if input_api.PresubmitLocalPath() != input_api.change.RepositoryRoot():
Sam Maierb926c58c2023-08-08 19:58:257167 return []
Hans Wennborg23a81d52023-03-24 16:38:137168
7169 DEPS_FILES = [ 'DEPS', 'buildtools/deps_revisions.gni' ]
7170
7171 file_filter = lambda f: f.LocalPath().replace(
7172 input_api.os_path.sep, '/') in DEPS_FILES
7173 changed_deps_files = input_api.AffectedFiles(file_filter=file_filter)
7174 if not changed_deps_files:
7175 return []
7176
7177 def LibcxxRevision(file):
7178 file = input_api.os_path.join(input_api.PresubmitLocalPath(),
7179 *file.split('/'))
7180 return input_api.re.search(
7181 r'libcxx_revision.*[:=].*[\'"](\w+)[\'"]',
7182 input_api.ReadFile(file)).group(1)
7183
7184 if len(set([LibcxxRevision(f) for f in DEPS_FILES])) == 1:
7185 return []
7186
7187 return [output_api.PresubmitError(
7188 'libcxx_revision not equal across %s' % ', '.join(DEPS_FILES),
7189 changed_deps_files)]
Arthur Sonzogni7109bd32023-10-03 10:34:427190
7191
7192def CheckDanglingUntriaged(input_api, output_api):
7193 """Warn developers adding DanglingUntriaged raw_ptr."""
7194
7195 # Ignore during git presubmit --all.
7196 #
7197 # This would be too costly, because this would check every lines of every
7198 # C++ files. Check from _BANNED_CPP_FUNCTIONS are also reading the whole
7199 # source code, but only once to apply every checks. It seems the bots like
7200 # `win-presubmit` are particularly sensitive to reading the files. Adding
7201 # this check caused the bot to run 2x longer. See https://crbug.com/1486612.
7202 if input_api.no_diffs:
Arthur Sonzogni9eafd222023-11-10 08:50:397203 return []
Arthur Sonzogni7109bd32023-10-03 10:34:427204
7205 def FilterFile(file):
7206 return input_api.FilterSourceFile(
7207 file,
7208 files_to_check=[r".*\.(h|cc|cpp|cxx|m|mm)$"],
7209 files_to_skip=[r"^base/allocator.*"],
7210 )
7211
7212 count = 0
7213 for f in input_api.AffectedSourceFiles(FilterFile):
Arthur Sonzogni9eafd222023-11-10 08:50:397214 count -= sum([l.count("DanglingUntriaged") for l in f.OldContents()])
7215 count += sum([l.count("DanglingUntriaged") for l in f.NewContents()])
Arthur Sonzogni7109bd32023-10-03 10:34:427216
7217 # Most likely, nothing changed:
7218 if count == 0:
7219 return []
7220
7221 # Congrats developers for improving it:
7222 if count < 0:
Arthur Sonzogni9eafd222023-11-10 08:50:397223 message = f"DanglingUntriaged pointers removed: {-count}\nThank you!"
Arthur Sonzogni7109bd32023-10-03 10:34:427224 return [output_api.PresubmitNotifyResult(message)]
7225
7226 # Check for 'DanglingUntriaged-notes' in the description:
7227 notes_regex = input_api.re.compile("DanglingUntriaged-notes[:=]")
7228 if any(
7229 notes_regex.match(line)
7230 for line in input_api.change.DescriptionText().splitlines()):
7231 return []
7232
7233 # Check for DanglingUntriaged-notes in the git footer:
7234 if input_api.change.GitFootersFromDescription().get(
7235 "DanglingUntriaged-notes", []):
7236 return []
7237
7238 message = (
Arthur Sonzogni9eafd222023-11-10 08:50:397239 "Unexpected new occurrences of `DanglingUntriaged` detected. Please\n" +
7240 "avoid adding new ones\n" +
7241 "\n" +
7242 "See documentation:\n" +
7243 "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md\n" +
7244 "\n" +
7245 "See also the guide to fix dangling pointers:\n" +
7246 "https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr_guide.md\n" +
7247 "\n" +
7248 "To disable this warning, please add in the commit description:\n" +
Alex Gough26dcd852023-12-22 16:47:197249 "DanglingUntriaged-notes: <rationale for new untriaged dangling " +
Arthur Sonzogni9eafd222023-11-10 08:50:397250 "pointers>"
Arthur Sonzogni7109bd32023-10-03 10:34:427251 )
7252 return [output_api.PresubmitPromptWarning(message)]
Jan Keitel77be7522023-10-12 20:40:497253
7254def CheckInlineConstexprDefinitionsInHeaders(input_api, output_api):
7255 """Checks that non-static constexpr definitions in headers are inline."""
7256 # In a properly formatted file, constexpr definitions inside classes or
7257 # structs will have additional whitespace at the beginning of the line.
7258 # The pattern looks for variables initialized as constexpr kVar = ...; or
7259 # constexpr kVar{...};
7260 # The pattern does not match expressions that have braces in kVar to avoid
7261 # matching constexpr functions.
7262 pattern = input_api.re.compile(r'^constexpr (?!inline )[^\(\)]*[={]')
7263 attribute_pattern = input_api.re.compile(r'(\[\[[a-zA-Z_:]+\]\]|[A-Z]+[A-Z_]+) ')
7264 problems = []
7265 for f in input_api.AffectedFiles():
7266 if not _IsCPlusPlusHeaderFile(input_api, f.LocalPath()):
7267 continue
7268
7269 for line_number, line in f.ChangedContents():
7270 line = attribute_pattern.sub('', line)
7271 if pattern.search(line):
7272 problems.append(
7273 f"{f.LocalPath()}: {line_number}\n {line}")
7274
7275 if problems:
7276 return [
7277 output_api.PresubmitPromptWarning(
7278 'Consider inlining constexpr variable definitions in headers '
7279 'outside of classes to avoid unnecessary copies of the '
7280 'constant. See https://abseil.io/tips/168 for more details.',
7281 problems)
7282 ]
7283 else:
7284 return []