blob: fed0d93d43605ca74d26f6d2324712f4ce596516 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[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
[email protected]f1293792009-07-31 18:09:567See http://dev.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"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0413 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py",
14 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py",
15 r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
16 r"^net[\\/]tools[\\/]spdyshark[\\/].*",
17 r"^skia[\\/].*",
Kent Tamura32dbbcb2018-11-30 12:28:4918 r"^third_party[\\/]blink[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0419 r"^third_party[\\/]breakpad[\\/].*",
Darwin Huangd74a9d32019-07-17 17:58:4620 # sqlite is an imported third party dependency.
21 r"^third_party[\\/]sqlite[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0422 r"^v8[\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5324 r".+_autogen\.h$",
John Budorick1e701d322019-09-11 23:35:1225 r".+_pb2\.py$",
Egor Paskoce145c42018-09-28 19:31:0426 r".+[\\/]pnacl_shim\.c$",
27 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
Egor Paskoce145c42018-09-28 19:31:0428 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1429 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0430 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5431 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0432 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4033)
[email protected]ca8d1982009-02-19 16:33:1234
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Fragment of a regular expression that matches C++ and Objective-C++
37# implementation files.
38_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
39
wnwenbdc444e2016-05-25 13:44:1540
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1941# Fragment of a regular expression that matches C++ and Objective-C++
42# header files.
43_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
44
45
[email protected]06e6d0ff2012-12-11 01:36:4446# Regular expression that matches code only used for test binaries
47# (best effort).
48_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0449 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4450 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4451 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1252 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1853 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4454 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0455 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0556 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0457 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4758 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0459 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0860 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0461 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4162 # EarlGrey app side code for tests.
63 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4464)
[email protected]ca8d1982009-02-19 16:33:1265
Daniel Bratell609102be2019-03-27 20:53:2166_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1567
[email protected]eea609a2011-11-18 13:10:1268_TEST_ONLY_WARNING = (
69 'You might be calling functions intended only for testing from\n'
70 'production code. It is OK to ignore this warning if you know what\n'
71 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0772 'not perfect. The commit queue will not block on this warning,\n'
73 'however the android-binary-size trybot will block if the method\n'
74 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1275
76
[email protected]cf9b78f2012-11-14 11:40:2877_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4078 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2179 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
80 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2881
Michael Thiessen44457642020-02-06 00:24:1582# Format: Sequence of tuples containing:
83# * Full import path.
84# * Sequence of strings to show when the pattern matches.
85# * Sequence of path or filename exceptions to this rule
86_BANNED_JAVA_IMPORTS = (
87 (
Colin Blundell170d78c82020-03-12 13:56:0488 'java.net.URI;',
Michael Thiessen44457642020-02-06 00:24:1589 (
90 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
91 ),
92 (
93 'net/android/javatests/src/org/chromium/net/'
94 'AndroidProxySelectorTest.java',
95 'components/cronet/',
96 ),
97 ),
98)
wnwenbdc444e2016-05-25 13:44:1599
Daniel Bratell609102be2019-03-27 20:53:21100# Format: Sequence of tuples containing:
101# * String pattern or, if starting with a slash, a regular expression.
102# * Sequence of strings to show when the pattern matches.
103# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:41104_BANNED_JAVA_FUNCTIONS = (
105 (
106 'StrictMode.allowThreadDiskReads()',
107 (
108 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
109 'directly.',
110 ),
111 False,
112 ),
113 (
114 'StrictMode.allowThreadDiskWrites()',
115 (
116 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
117 'directly.',
118 ),
119 False,
120 ),
121)
122
Daniel Bratell609102be2019-03-27 20:53:21123# Format: Sequence of tuples containing:
124# * String pattern or, if starting with a slash, a regular expression.
125# * Sequence of strings to show when the pattern matches.
126# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59127_BANNED_OBJC_FUNCTIONS = (
128 (
129 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59132 'prohibited. Please use CrTrackingArea instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 False,
136 ),
137 (
[email protected]eaae1972014-04-16 04:17:26138 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20139 (
140 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59141 'instead.',
142 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
143 ),
144 False,
145 ),
146 (
147 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20148 (
149 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59150 'Please use |convertPoint:(point) fromView:nil| instead.',
151 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
152 ),
153 True,
154 ),
155 (
156 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59159 'Please use |convertPoint:(point) toView:nil| instead.',
160 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
161 ),
162 True,
163 ),
164 (
165 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59168 'Please use |convertRect:(point) fromView:nil| instead.',
169 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
170 ),
171 True,
172 ),
173 (
174 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20175 (
176 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59177 'Please use |convertRect:(point) toView:nil| instead.',
178 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
179 ),
180 True,
181 ),
182 (
183 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20184 (
185 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59186 'Please use |convertSize:(point) fromView:nil| instead.',
187 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
188 ),
189 True,
190 ),
191 (
192 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20193 (
194 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59195 'Please use |convertSize:(point) toView:nil| instead.',
196 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
197 ),
198 True,
199 ),
jif65398702016-10-27 10:19:48200 (
201 r"/\s+UTF8String\s*]",
202 (
203 'The use of -[NSString UTF8String] is dangerous as it can return null',
204 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
205 'Please use |SysNSStringToUTF8| instead.',
206 ),
207 True,
208 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34209 (
210 r'__unsafe_unretained',
211 (
212 'The use of __unsafe_unretained is almost certainly wrong, unless',
213 'when interacting with NSFastEnumeration or NSInvocation.',
214 'Please use __weak in files build with ARC, nothing otherwise.',
215 ),
216 False,
217 ),
Avi Drissman7382afa02019-04-29 23:27:13218 (
219 'freeWhenDone:NO',
220 (
221 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
222 'Foundation types is prohibited.',
223 ),
224 True,
225 ),
[email protected]127f18ec2012-06-16 05:05:59226)
227
Daniel Bratell609102be2019-03-27 20:53:21228# Format: Sequence of tuples containing:
229# * String pattern or, if starting with a slash, a regular expression.
230# * Sequence of strings to show when the pattern matches.
231# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54232_BANNED_IOS_OBJC_FUNCTIONS = (
233 (
234 r'/\bTEST[(]',
235 (
236 'TEST() macro should not be used in Objective-C++ code as it does not ',
237 'drain the autorelease pool at the end of the test. Use TEST_F() ',
238 'macro instead with a fixture inheriting from PlatformTest (or a ',
239 'typedef).'
240 ),
241 True,
242 ),
243 (
244 r'/\btesting::Test\b',
245 (
246 'testing::Test should not be used in Objective-C++ code as it does ',
247 'not drain the autorelease pool at the end of the test. Use ',
248 'PlatformTest instead.'
249 ),
250 True,
251 ),
252)
253
Peter K. Lee6c03ccff2019-07-15 14:40:05254# Format: Sequence of tuples containing:
255# * String pattern or, if starting with a slash, a regular expression.
256# * Sequence of strings to show when the pattern matches.
257# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
258_BANNED_IOS_EGTEST_FUNCTIONS = (
259 (
260 r'/\bEXPECT_OCMOCK_VERIFY\b',
261 (
262 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
263 'it is meant for GTests. Use [mock verify] instead.'
264 ),
265 True,
266 ),
267)
268
danakj7a2b7082019-05-21 21:13:51269# Directories that contain deprecated Bind() or Callback types.
270# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36271# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51272# echo "-- $i"
danakj710b4c02019-11-28 16:08:45273# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51274# done
275#
276# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
277# when they have been converted to modern callback types (OnceCallback,
278# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
279# checks for them and prevent regressions.
280_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
danakj7a2b7082019-05-21 21:13:51281 '^apps/',
danakj7a2b7082019-05-21 21:13:51282 '^base/callback.h', # Intentional.
283 '^chrome/app/',
284 '^chrome/browser/',
285 '^chrome/chrome_elf/',
danakj7a2b7082019-05-21 21:13:51286 '^chrome/common/',
287 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51288 '^chrome/renderer/',
289 '^chrome/services/',
290 '^chrome/test/',
291 '^chrome/tools/',
292 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51293 '^chromecast/media/',
294 '^chromecast/metrics/',
295 '^chromecast/net/',
296 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51297 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51298 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51299 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51300 '^components/arc/',
301 '^components/assist_ranker/',
302 '^components/autofill/',
303 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51304 '^components/browser_watcher/',
danakj7a2b7082019-05-21 21:13:51305 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51306 '^components/chromeos_camera/',
307 '^components/component_updater/',
308 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51309 '^components/cronet/',
310 '^components/data_reduction_proxy/',
danakj7a2b7082019-05-21 21:13:51311 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36312 '^components/dom_distiller/',
Joey Scarr164d7072020-04-21 03:13:39313 '^components/download/internal/common/',
danakj7a2b7082019-05-21 21:13:51314 '^components/drive/',
315 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51316 '^components/feature_engagement/',
317 '^components/feedback/',
318 '^components/flags_ui/',
319 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51320 '^components/guest_view/',
321 '^components/heap_profiling/',
322 '^components/history/',
323 '^components/image_fetcher/',
324 '^components/invalidation/',
325 '^components/keyed_service/',
326 '^components/login/',
327 '^components/metrics/',
328 '^components/metrics_services_manager/',
329 '^components/nacl/',
330 '^components/navigation_interception/',
331 '^components/net_log/',
332 '^components/network_time/',
333 '^components/ntp_snippets/',
334 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51335 '^components/offline_pages/',
336 '^components/omnibox/',
337 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51338 '^components/password_manager/',
339 '^components/payments/',
340 '^components/plugins/',
341 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51342 '^components/proxy_config/',
343 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51344 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51345 '^components/rlz/',
346 '^components/safe_browsing/',
347 '^components/search_engines/',
348 '^components/search_provider_logos/',
349 '^components/security_interstitials/',
350 '^components/security_state/',
351 '^components/services/',
352 '^components/sessions/',
353 '^components/signin/',
354 '^components/ssl_errors/',
355 '^components/storage_monitor/',
356 '^components/subresource_filter/',
357 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51358 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51359 '^components/sync_preferences/',
360 '^components/sync_sessions/',
361 '^components/test/',
362 '^components/tracing/',
363 '^components/translate/',
364 '^components/ukm/',
365 '^components/update_client/',
366 '^components/upload_list/',
367 '^components/variations/',
368 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51369 '^components/webcrypto/',
370 '^components/webdata/',
371 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51372 '^device/bluetooth/',
Alan Cutter04a00642020-03-02 01:45:20373 '^extensions/browser/',
374 '^extensions/renderer/',
danakj7a2b7082019-05-21 21:13:51375 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51376 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51377 '^ios/chrome/',
378 '^ios/components/',
379 '^ios/net/',
380 '^ios/web/',
381 '^ios/web_view/',
382 '^ipc/',
danakj7a2b7082019-05-21 21:13:51383 '^media/base/',
danakjc8576092019-11-26 19:01:36384 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51385 '^media/cast/',
386 '^media/cdm/',
387 '^media/device_monitors/',
danakj7a2b7082019-05-21 21:13:51388 '^media/filters/',
389 '^media/formats/',
390 '^media/gpu/',
391 '^media/mojo/',
danakj7a2b7082019-05-21 21:13:51392 '^media/renderers/',
danakj7a2b7082019-05-21 21:13:51393 '^net/',
394 '^ppapi/proxy/',
395 '^ppapi/shared_impl/',
396 '^ppapi/tests/',
397 '^ppapi/thunk/',
398 '^remoting/base/',
399 '^remoting/client/',
danakj7a2b7082019-05-21 21:13:51400 '^remoting/host/',
401 '^remoting/internal/',
danakj7a2b7082019-05-21 21:13:51402 '^remoting/protocol/',
danakj7a2b7082019-05-21 21:13:51403 '^services/',
danakj7a2b7082019-05-21 21:13:51404 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51405 '^tools/clang/base_bind_rewriters/', # Intentional.
406 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51407))
[email protected]127f18ec2012-06-16 05:05:59408
Daniel Bratell609102be2019-03-27 20:53:21409# Format: Sequence of tuples containing:
410# * String pattern or, if starting with a slash, a regular expression.
411# * Sequence of strings to show when the pattern matches.
412# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
413# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59414_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20415 (
Dave Tapuska98199b612019-07-10 13:30:44416 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53417 (
418 'New code should not use NULL. Use nullptr instead.',
419 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20420 False,
thomasandersone7caaa9b2017-03-29 19:22:53421 (),
422 ),
Peter Kasting94a56c42019-10-25 21:54:04423 (
424 r'/\busing namespace ',
425 (
426 'Using directives ("using namespace x") are banned by the Google Style',
427 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
428 'Explicitly qualify symbols or use using declarations ("using x::foo").',
429 ),
430 True,
431 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
432 ),
Antonio Gomes07300d02019-03-13 20:59:57433 # Make sure that gtest's FRIEND_TEST() macro is not used; the
434 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
435 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53436 (
[email protected]23e6cbc2012-06-16 18:51:20437 'FRIEND_TEST(',
438 (
[email protected]e3c945502012-06-26 20:01:49439 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20440 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
441 ),
442 False,
[email protected]7345da02012-11-27 14:31:49443 (),
[email protected]23e6cbc2012-06-16 18:51:20444 ),
445 (
Dave Tapuska98199b612019-07-10 13:30:44446 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53447 (
448 'Chrome clients wishing to select events on X windows should use',
449 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
450 'you are selecting events from the GPU process, or if you are using',
451 'an XDisplay other than gfx::GetXDisplay().',
452 ),
453 True,
454 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40455 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04456 r"^ui[\\/]gl[\\/].*\.cc$",
457 r"^media[\\/]gpu[\\/].*\.cc$",
458 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53459 ),
460 ),
461 (
Dave Tapuska98199b612019-07-10 13:30:44462 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20463 (
thomasanderson11aa41d2017-06-08 22:22:38464 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20465 ),
466 True,
467 (
Egor Paskoce145c42018-09-28 19:31:04468 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
469 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
470 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20471 ),
472 ),
473 (
tomhudsone2c14d552016-05-26 17:07:46474 'setMatrixClip',
475 (
476 'Overriding setMatrixClip() is prohibited; ',
477 'the base function is deprecated. ',
478 ),
479 True,
480 (),
481 ),
482 (
[email protected]52657f62013-05-20 05:30:31483 'SkRefPtr',
484 (
485 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22486 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31487 ),
488 True,
489 (),
490 ),
491 (
492 'SkAutoRef',
493 (
494 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22495 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31496 ),
497 True,
498 (),
499 ),
500 (
501 'SkAutoTUnref',
502 (
503 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22504 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31505 ),
506 True,
507 (),
508 ),
509 (
510 'SkAutoUnref',
511 (
512 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
513 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22514 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31515 ),
516 True,
517 (),
518 ),
[email protected]d89eec82013-12-03 14:10:59519 (
520 r'/HANDLE_EINTR\(.*close',
521 (
522 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
523 'descriptor will be closed, and it is incorrect to retry the close.',
524 'Either call close directly and ignore its return value, or wrap close',
525 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
526 ),
527 True,
528 (),
529 ),
530 (
531 r'/IGNORE_EINTR\((?!.*close)',
532 (
533 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
534 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
535 ),
536 True,
537 (
538 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04539 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
540 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59541 ),
542 ),
[email protected]ec5b3f02014-04-04 18:43:43543 (
544 r'/v8::Extension\(',
545 (
546 'Do not introduce new v8::Extensions into the code base, use',
547 'gin::Wrappable instead. See http://crbug.com/334679',
548 ),
549 True,
[email protected]f55c90ee62014-04-12 00:50:03550 (
Egor Paskoce145c42018-09-28 19:31:04551 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03552 ),
[email protected]ec5b3f02014-04-04 18:43:43553 ),
skyostilf9469f72015-04-20 10:38:52554 (
jame2d1a952016-04-02 00:27:10555 '#pragma comment(lib,',
556 (
557 'Specify libraries to link with in build files and not in the source.',
558 ),
559 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41560 (
tzik3f295992018-12-04 20:32:23561 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04562 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41563 ),
jame2d1a952016-04-02 00:27:10564 ),
fdorayc4ac18d2017-05-01 21:39:59565 (
Gabriel Charette7cc6c432018-04-25 20:52:02566 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59567 (
568 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
569 ),
570 False,
571 (),
572 ),
573 (
Gabriel Charette7cc6c432018-04-25 20:52:02574 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59575 (
576 'Consider using THREAD_CHECKER macros instead of the class directly.',
577 ),
578 False,
579 (),
580 ),
dbeamb6f4fde2017-06-15 04:03:06581 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06582 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
583 (
584 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
585 'deprecated (http://crbug.com/634507). Please avoid converting away',
586 'from the Time types in Chromium code, especially if any math is',
587 'being done on time values. For interfacing with platform/library',
588 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
589 'type converter methods instead. For faking TimeXXX values (for unit',
590 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
591 'other use cases, please contact base/time/OWNERS.',
592 ),
593 False,
594 (),
595 ),
596 (
dbeamb6f4fde2017-06-15 04:03:06597 'CallJavascriptFunctionUnsafe',
598 (
599 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
600 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
601 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
602 ),
603 False,
604 (
Egor Paskoce145c42018-09-28 19:31:04605 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
606 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
607 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06608 ),
609 ),
dskiba1474c2bfd62017-07-20 02:19:24610 (
611 'leveldb::DB::Open',
612 (
613 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
614 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
615 "Chrome's tracing, making their memory usage visible.",
616 ),
617 True,
618 (
619 r'^third_party/leveldatabase/.*\.(cc|h)$',
620 ),
Gabriel Charette0592c3a2017-07-26 12:02:04621 ),
622 (
Chris Mumfordc38afb62017-10-09 17:55:08623 'leveldb::NewMemEnv',
624 (
625 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58626 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
627 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08628 ),
629 True,
630 (
631 r'^third_party/leveldatabase/.*\.(cc|h)$',
632 ),
633 ),
634 (
Gabriel Charetted9839bc2017-07-29 14:17:47635 'RunLoop::QuitCurrent',
636 (
Robert Liao64b7ab22017-08-04 23:03:43637 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
638 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47639 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41640 False,
Gabriel Charetted9839bc2017-07-29 14:17:47641 (),
Gabriel Charettea44975052017-08-21 23:14:04642 ),
643 (
644 'base::ScopedMockTimeMessageLoopTaskRunner',
645 (
Gabriel Charette87cc1af2018-04-25 20:52:51646 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11647 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51648 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
649 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
650 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04651 ),
Gabriel Charette87cc1af2018-04-25 20:52:51652 False,
Gabriel Charettea44975052017-08-21 23:14:04653 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57654 ),
655 (
Dave Tapuska98199b612019-07-10 13:30:44656 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57657 (
658 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02659 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57660 ),
661 True,
662 (),
Francois Doray43670e32017-09-27 12:40:38663 ),
664 (
Peter Kasting991618a62019-06-17 22:00:09665 r'/\bstd::stoi\b',
666 (
667 'std::stoi uses exceptions to communicate results. ',
668 'Use base::StringToInt() instead.',
669 ),
670 True,
671 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
672 ),
673 (
674 r'/\bstd::stol\b',
675 (
676 'std::stol uses exceptions to communicate results. ',
677 'Use base::StringToInt() instead.',
678 ),
679 True,
680 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
681 ),
682 (
683 r'/\bstd::stoul\b',
684 (
685 'std::stoul uses exceptions to communicate results. ',
686 'Use base::StringToUint() instead.',
687 ),
688 True,
689 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
690 ),
691 (
692 r'/\bstd::stoll\b',
693 (
694 'std::stoll uses exceptions to communicate results. ',
695 'Use base::StringToInt64() instead.',
696 ),
697 True,
698 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
699 ),
700 (
701 r'/\bstd::stoull\b',
702 (
703 'std::stoull uses exceptions to communicate results. ',
704 'Use base::StringToUint64() instead.',
705 ),
706 True,
707 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
708 ),
709 (
710 r'/\bstd::stof\b',
711 (
712 'std::stof uses exceptions to communicate results. ',
713 'For locale-independent values, e.g. reading numbers from disk',
714 'profiles, use base::StringToDouble().',
715 'For user-visible values, parse using ICU.',
716 ),
717 True,
718 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
719 ),
720 (
721 r'/\bstd::stod\b',
722 (
723 'std::stod uses exceptions to communicate results. ',
724 'For locale-independent values, e.g. reading numbers from disk',
725 'profiles, use base::StringToDouble().',
726 'For user-visible values, parse using ICU.',
727 ),
728 True,
729 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
730 ),
731 (
732 r'/\bstd::stold\b',
733 (
734 'std::stold uses exceptions to communicate results. ',
735 'For locale-independent values, e.g. reading numbers from disk',
736 'profiles, use base::StringToDouble().',
737 'For user-visible values, parse using ICU.',
738 ),
739 True,
740 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
741 ),
742 (
Daniel Bratell69334cc2019-03-26 11:07:45743 r'/\bstd::to_string\b',
744 (
745 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09746 'For locale-independent strings, e.g. writing numbers to disk',
747 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45748 'For user-visible strings, use base::FormatNumber() and',
749 'the related functions in base/i18n/number_formatting.h.',
750 ),
Peter Kasting991618a62019-06-17 22:00:09751 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21752 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45753 ),
754 (
755 r'/\bstd::shared_ptr\b',
756 (
757 'std::shared_ptr should not be used. Use scoped_refptr instead.',
758 ),
759 True,
Andreas Haas63f58792019-11-07 10:56:44760 [_THIRD_PARTY_EXCEPT_BLINK,
761 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
762 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21763 ),
764 (
Peter Kasting991618a62019-06-17 22:00:09765 r'/\bstd::weak_ptr\b',
766 (
767 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
768 ),
769 True,
770 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
771 ),
772 (
Daniel Bratell609102be2019-03-27 20:53:21773 r'/\blong long\b',
774 (
775 'long long is banned. Use stdint.h if you need a 64 bit number.',
776 ),
777 False, # Only a warning since it is already used.
778 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
779 ),
780 (
781 r'/\bstd::bind\b',
782 (
783 'std::bind is banned because of lifetime risks.',
784 'Use base::BindOnce or base::BindRepeating instead.',
785 ),
786 True,
787 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
788 ),
789 (
790 r'/\b#include <chrono>\b',
791 (
792 '<chrono> overlaps with Time APIs in base. Keep using',
793 'base classes.',
794 ),
795 True,
796 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
797 ),
798 (
799 r'/\b#include <exception>\b',
800 (
801 'Exceptions are banned and disabled in Chromium.',
802 ),
803 True,
804 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
805 ),
806 (
807 r'/\bstd::function\b',
808 (
809 'std::function is banned. Instead use base::Callback which directly',
810 'supports Chromium\'s weak pointers, ref counting and more.',
811 ),
Peter Kasting991618a62019-06-17 22:00:09812 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21813 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
814 ),
815 (
816 r'/\b#include <random>\b',
817 (
818 'Do not use any random number engines from <random>. Instead',
819 'use base::RandomBitGenerator.',
820 ),
821 True,
822 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
823 ),
824 (
825 r'/\bstd::ratio\b',
826 (
827 'std::ratio is banned by the Google Style Guide.',
828 ),
829 True,
830 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45831 ),
832 (
Francois Doray43670e32017-09-27 12:40:38833 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
834 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
835 (
836 'Use the new API in base/threading/thread_restrictions.h.',
837 ),
Gabriel Charette04b138f2018-08-06 00:03:22838 False,
Francois Doray43670e32017-09-27 12:40:38839 (),
840 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38841 (
danakj7a2b7082019-05-21 21:13:51842 r'/\bbase::Bind\(',
843 (
844 'Please use base::Bind{Once,Repeating} instead',
845 'of base::Bind. (crbug.com/714018)',
846 ),
847 False,
Erik Staaba737d7602019-11-25 18:41:07848 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51849 ),
850 (
851 r'/\bbase::Callback[<:]',
852 (
853 'Please use base::{Once,Repeating}Callback instead',
854 'of base::Callback. (crbug.com/714018)',
855 ),
856 False,
Erik Staaba737d7602019-11-25 18:41:07857 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51858 ),
859 (
860 r'/\bbase::Closure\b',
861 (
862 'Please use base::{Once,Repeating}Closure instead',
863 'of base::Closure. (crbug.com/714018)',
864 ),
865 False,
Erik Staaba737d7602019-11-25 18:41:07866 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51867 ),
868 (
Michael Giuffrida7f93d6922019-04-19 14:39:58869 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19870 (
871 'RunMessageLoop is deprecated, use RunLoop instead.',
872 ),
873 False,
874 (),
875 ),
876 (
Dave Tapuska98199b612019-07-10 13:30:44877 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19878 (
879 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
880 ),
881 False,
882 (),
883 ),
884 (
Dave Tapuska98199b612019-07-10 13:30:44885 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19886 (
887 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
888 "if you're convinced you need this.",
889 ),
890 False,
891 (),
892 ),
893 (
Dave Tapuska98199b612019-07-10 13:30:44894 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19895 (
896 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04897 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19898 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
899 'async events instead of flushing threads.',
900 ),
901 False,
902 (),
903 ),
904 (
905 r'MessageLoopRunner',
906 (
907 'MessageLoopRunner is deprecated, use RunLoop instead.',
908 ),
909 False,
910 (),
911 ),
912 (
Dave Tapuska98199b612019-07-10 13:30:44913 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19914 (
915 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
916 "gab@ if you found a use case where this is the only solution.",
917 ),
918 False,
919 (),
920 ),
921 (
Victor Costane48a2e82019-03-15 22:02:34922 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16923 (
Victor Costane48a2e82019-03-15 22:02:34924 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16925 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
926 ),
927 True,
928 (
929 r'^sql/initialization\.(cc|h)$',
930 r'^third_party/sqlite/.*\.(c|cc|h)$',
931 ),
932 ),
Matt Menke7f520a82018-03-28 21:38:37933 (
Dave Tapuska98199b612019-07-10 13:30:44934 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47935 (
936 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
937 'base::RandomShuffle instead.'
938 ),
939 True,
940 (),
941 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24942 (
943 'ios/web/public/test/http_server',
944 (
945 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
946 ),
947 False,
948 (),
949 ),
Robert Liao764c9492019-01-24 18:46:28950 (
951 'GetAddressOf',
952 (
953 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46954 'implicated in a few leaks. Use operator& instead. See ',
955 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28956 ),
957 True,
958 (),
959 ),
Antonio Gomes07300d02019-03-13 20:59:57960 (
961 'DEFINE_TYPE_CASTS',
962 (
963 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
964 '//third_party/blink/renderer/platform/casting.h.'
965 ),
966 True,
967 (
968 r'^third_party/blink/renderer/.*\.(cc|h)$',
969 ),
970 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38971 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45972 r'/\bIsHTML.+Element\(\b',
973 (
974 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
975 ' helpers IsA<HTMLXXXXElement> from ',
976 '//third_party/blink/renderer/platform/casting.h.'
977 ),
978 False,
979 (
980 r'^third_party/blink/renderer/.*\.(cc|h)$',
981 ),
982 ),
983 (
984 r'/\bToHTML.+Element(|OrNull)\(\b',
985 (
986 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
987 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
988 'and DynamicTo<HTMLXXXXElement> from ',
989 '//third_party/blink/renderer/platform/casting.h.'
990 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
991 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
992 ),
993 False,
994 (
995 r'^third_party/blink/renderer/.*\.(cc|h)$',
996 ),
997 ),
998 (
Kinuko Yasuda376c2ce12019-04-16 01:20:37999 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381000 (
1001 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1002 ),
1003 True,
1004 (),
1005 ),
Ben Lewisa9514602019-04-29 17:53:051006 (
1007 'SHFileOperation',
1008 (
1009 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1010 'complex functions to achieve the same goals. Use IFileOperation for ',
1011 'any esoteric actions instead.'
1012 ),
1013 True,
1014 (),
1015 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181016 (
Cliff Smolinsky81951642019-04-30 21:39:511017 'StringFromGUID2',
1018 (
1019 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1020 'Use base::win::String16FromGUID instead.'
1021 ),
1022 True,
1023 (
1024 r'/base/win/win_util_unittest.cc'
1025 ),
1026 ),
1027 (
1028 'StringFromCLSID',
1029 (
1030 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1031 'Use base::win::String16FromGUID instead.'
1032 ),
1033 True,
1034 (
1035 r'/base/win/win_util_unittest.cc'
1036 ),
1037 ),
1038 (
Avi Drissman7382afa02019-04-29 23:27:131039 'kCFAllocatorNull',
1040 (
1041 'The use of kCFAllocatorNull with the NoCopy creation of ',
1042 'CoreFoundation types is prohibited.',
1043 ),
1044 True,
1045 (),
1046 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291047 (
1048 'mojo::ConvertTo',
1049 (
1050 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1051 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1052 'StringTraits if you would like to convert between custom types and',
1053 'the wire format of mojom types.'
1054 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221055 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291056 (
Wezf89dec092019-09-11 19:38:331057 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1058 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291059 r'^third_party/blink/.*\.(cc|h)$',
1060 r'^content/renderer/.*\.(cc|h)$',
1061 ),
1062 ),
Robert Liao1d78df52019-11-11 20:02:011063 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161064 'GetInterfaceProvider',
1065 (
1066 'InterfaceProvider is deprecated.',
1067 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1068 'or Platform::GetBrowserInterfaceBroker.'
1069 ),
1070 False,
1071 (),
1072 ),
1073 (
Robert Liao1d78df52019-11-11 20:02:011074 'CComPtr',
1075 (
1076 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1077 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1078 'details.'
1079 ),
1080 False,
1081 (),
1082 ),
Xiaohan Wang72bd2ba2020-02-18 21:38:201083 (
1084 r'/\b(IFACE|STD)METHOD_?\(',
1085 (
1086 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1087 'Instead, always use IFACEMETHODIMP in the declaration.'
1088 ),
1089 False,
1090 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1091 ),
Allen Bauer53b43fb12020-03-12 17:21:471092 (
1093 'set_owned_by_client',
1094 (
1095 'set_owned_by_client is deprecated.',
1096 'views::View already owns the child views by default. This introduces ',
1097 'a competing ownership model which makes the code difficult to reason ',
1098 'about. See http://crbug.com/1044687 for more details.'
1099 ),
1100 False,
1101 (),
1102 ),
Eric Secklerbe6f48d2020-05-06 18:09:121103 (
1104 r'/\bTRACE_EVENT_ASYNC_',
1105 (
1106 'Please use TRACE_EVENT_NESTABLE_ASYNC_.. macros instead',
1107 'of TRACE_EVENT_ASYNC_.. (crbug.com/1038710).',
1108 ),
1109 False,
1110 (
1111 r'^base/trace_event/.*',
1112 r'^base/tracing/.*',
1113 ),
1114 ),
[email protected]127f18ec2012-06-16 05:05:591115)
1116
Mario Sanchez Prada2472cab2019-09-18 10:58:311117# Format: Sequence of tuples containing:
1118# * String pattern or, if starting with a slash, a regular expression.
1119# * Sequence of strings to show when the pattern matches.
1120_DEPRECATED_MOJO_TYPES = (
1121 (
1122 r'/\bmojo::AssociatedBinding\b',
1123 (
1124 'mojo::AssociatedBinding<Interface> is deprecated.',
1125 'Use mojo::AssociatedReceiver<Interface> instead.',
1126 ),
1127 ),
1128 (
1129 r'/\bmojo::AssociatedBindingSet\b',
1130 (
1131 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1132 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1133 ),
1134 ),
1135 (
1136 r'/\bmojo::AssociatedInterfacePtr\b',
1137 (
1138 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1139 'Use mojo::AssociatedRemote<Interface> instead.',
1140 ),
1141 ),
1142 (
1143 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1144 (
1145 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1146 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1147 ),
1148 ),
1149 (
1150 r'/\bmojo::AssociatedInterfaceRequest\b',
1151 (
1152 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1153 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1154 ),
1155 ),
1156 (
1157 r'/\bmojo::Binding\b',
1158 (
1159 'mojo::Binding<Interface> is deprecated.',
1160 'Use mojo::Receiver<Interface> instead.',
1161 ),
1162 ),
1163 (
1164 r'/\bmojo::BindingSet\b',
1165 (
1166 'mojo::BindingSet<Interface> is deprecated.',
1167 'Use mojo::ReceiverSet<Interface> instead.',
1168 ),
1169 ),
1170 (
1171 r'/\bmojo::InterfacePtr\b',
1172 (
1173 'mojo::InterfacePtr<Interface> is deprecated.',
1174 'Use mojo::Remote<Interface> instead.',
1175 ),
1176 ),
1177 (
1178 r'/\bmojo::InterfacePtrInfo\b',
1179 (
1180 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1181 'Use mojo::PendingRemote<Interface> instead.',
1182 ),
1183 ),
1184 (
1185 r'/\bmojo::InterfaceRequest\b',
1186 (
1187 'mojo::InterfaceRequest<Interface> is deprecated.',
1188 'Use mojo::PendingReceiver<Interface> instead.',
1189 ),
1190 ),
1191 (
1192 r'/\bmojo::MakeRequest\b',
1193 (
1194 'mojo::MakeRequest is deprecated.',
1195 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1196 ),
1197 ),
1198 (
1199 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1200 (
1201 'mojo::MakeRequest is deprecated.',
1202 'Use mojo::AssociatedRemote::'
1203 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1204 ),
1205 ),
1206 (
1207 r'/\bmojo::MakeStrongBinding\b',
1208 (
1209 'mojo::MakeStrongBinding is deprecated.',
1210 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1211 'mojo::MakeSelfOwnedReceiver() instead.',
1212 ),
1213 ),
1214 (
1215 r'/\bmojo::MakeStrongAssociatedBinding\b',
1216 (
1217 'mojo::MakeStrongAssociatedBinding is deprecated.',
1218 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1219 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1220 ),
1221 ),
1222 (
1223 r'/\bmojo::StrongAssociatedBindingSet\b',
1224 (
1225 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1226 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1227 ),
1228 ),
1229 (
1230 r'/\bmojo::StrongBindingSet\b',
1231 (
1232 'mojo::StrongBindingSet<Interface> is deprecated.',
1233 'Use mojo::UniqueReceiverSet<Interface> instead.',
1234 ),
1235 ),
1236)
wnwenbdc444e2016-05-25 13:44:151237
mlamouria82272622014-09-16 18:45:041238_IPC_ENUM_TRAITS_DEPRECATED = (
1239 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501240 'See http://www.chromium.org/Home/chromium-security/education/'
1241 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041242
Stephen Martinis97a394142018-06-07 23:06:051243_LONG_PATH_ERROR = (
1244 'Some files included in this CL have file names that are too long (> 200'
1245 ' characters). If committed, these files will cause issues on Windows. See'
1246 ' https://crbug.com/612667 for more details.'
1247)
1248
Shenghua Zhangbfaa38b82017-11-16 21:58:021249_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041250 r".*[\\/]BuildHooksAndroidImpl\.java",
1251 r".*[\\/]LicenseContentProvider\.java",
1252 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281253 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021254]
[email protected]127f18ec2012-06-16 05:05:591255
Mohamed Heikald048240a2019-11-12 16:57:371256# List of image extensions that are used as resources in chromium.
1257_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1258
Sean Kau46e29bc2017-08-28 16:31:161259# These paths contain test data and other known invalid JSON files.
Erik Staab2dd72b12020-04-16 15:03:401260_KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041261 r'test[\\/]data[\\/]',
Erik Staab2dd72b12020-04-16 15:03:401262 r'testing[\\/]buildbot[\\/]',
Egor Paskoce145c42018-09-28 19:31:041263 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1264 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041265 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431266 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161267]
1268
1269
[email protected]b00342e7f2013-03-26 16:21:541270_VALID_OS_MACROS = (
1271 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081272 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541273 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121274 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541275 'OS_BSD',
1276 'OS_CAT', # For testing.
1277 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041278 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371280 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541281 'OS_IOS',
1282 'OS_LINUX',
1283 'OS_MACOSX',
1284 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211285 'OS_NACL_NONSFI',
1286 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121287 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541288 'OS_OPENBSD',
1289 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371290 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541291 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541292 'OS_WIN',
1293)
1294
1295
agrievef32bcc72016-04-04 14:57:401296_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391297 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361298 'base/android/jni_generator/jni_generator.pydeps',
1299 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221300 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361301 'build/android/gyp/aar.pydeps',
1302 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271303 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381305 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361306 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111307 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361309 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361310 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111311 'build/android/gyp/create_app_bundle_apks.pydeps',
1312 'build/android/gyp/create_app_bundle.pydeps',
1313 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361314 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221315 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361316 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591317 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361318 'build/android/gyp/dex.pydeps',
Andrew Grieve723c1502020-04-23 16:27:421319 'build/android/gyp/dex_jdk_libs.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361320 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361321 'build/android/gyp/filter_zip.pydeps',
1322 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361323 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361324 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581325 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361326 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261327 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve5853fbd2020-02-20 17:26:011328 'build/android/gyp/jetify_jar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361329 'build/android/gyp/jinja_template.pydeps',
1330 'build/android/gyp/lint.pydeps',
1331 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361332 'build/android/gyp/merge_manifest.pydeps',
1333 'build/android/gyp/prepare_resources.pydeps',
1334 'build/android/gyp/proguard.pydeps',
Peter Wen578730b2020-03-19 19:55:461335 'build/android/gyp/turbine.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241336 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361337 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461338 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561339 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361340 'build/android/incremental_install/generate_android_manifest.pydeps',
1341 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221342 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401343 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041344 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361345 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411346 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051347 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191348 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431349 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021350 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401351]
1352
wnwenbdc444e2016-05-25 13:44:151353
agrievef32bcc72016-04-04 14:57:401354_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421355 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131356 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421357 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1358 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131359 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191360 ('third_party/blink/renderer/bindings/scripts/'
1361 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061362 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221363 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401364]
1365
wnwenbdc444e2016-05-25 13:44:151366
agrievef32bcc72016-04-04 14:57:401367_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1368
1369
Eric Boren6fd2b932018-01-25 15:05:081370# Bypass the AUTHORS check for these accounts.
1371_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591372 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451373 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591374 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521375 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1376 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041377 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271378 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041379 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301380 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081381
1382
Daniel Bratell65b033262019-04-23 08:17:061383def _IsCPlusPlusFile(input_api, file_path):
1384 """Returns True if this file contains C++-like code (and not Python,
1385 Go, Java, MarkDown, ...)"""
1386
1387 ext = input_api.os_path.splitext(file_path)[1]
1388 # This list is compatible with CppChecker.IsCppFile but we should
1389 # consider adding ".c" to it. If we do that we can use this function
1390 # at more places in the code.
1391 return ext in (
1392 '.h',
1393 '.cc',
1394 '.cpp',
1395 '.m',
1396 '.mm',
1397 )
1398
1399def _IsCPlusPlusHeaderFile(input_api, file_path):
1400 return input_api.os_path.splitext(file_path)[1] == ".h"
1401
1402
1403def _IsJavaFile(input_api, file_path):
1404 return input_api.os_path.splitext(file_path)[1] == ".java"
1405
1406
1407def _IsProtoFile(input_api, file_path):
1408 return input_api.os_path.splitext(file_path)[1] == ".proto"
1409
[email protected]55459852011-08-10 15:17:191410def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1411 """Attempts to prevent use of functions intended only for testing in
1412 non-testing code. For now this is just a best-effort implementation
1413 that ignores header files and may have some false positives. A
1414 better implementation would probably need a proper C++ parser.
1415 """
1416 # We only scan .cc files and the like, as the declaration of
1417 # for-testing functions in header files are hard to distinguish from
1418 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491419 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191420
jochenc0d4808c2015-07-27 09:25:421421 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191422 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091423 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191424 exclusion_pattern = input_api.re.compile(
1425 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1426 base_function_pattern, base_function_pattern))
1427
1428 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441429 black_list = (_EXCLUDED_PATHS +
1430 _TEST_CODE_EXCLUDED_PATHS +
1431 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191432 return input_api.FilterSourceFile(
1433 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491434 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191435 black_list=black_list)
1436
1437 problems = []
1438 for f in input_api.AffectedSourceFiles(FilterFile):
1439 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241440 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031441 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461442 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031443 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191444 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031445 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191446
1447 if problems:
[email protected]f7051d52013-04-02 18:31:421448 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031449 else:
1450 return []
[email protected]55459852011-08-10 15:17:191451
1452
Vaclav Brozek7dbc28c2018-03-27 08:35:231453def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1454 """This is a simplified version of
1455 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1456 """
1457 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1458 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1459 name_pattern = r'ForTest(s|ing)?'
1460 # Describes an occurrence of "ForTest*" inside a // comment.
1461 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1462 # Catch calls.
1463 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1464 # Ignore definitions. (Comments are ignored separately.)
1465 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1466
1467 problems = []
1468 sources = lambda x: input_api.FilterSourceFile(
1469 x,
1470 black_list=(('(?i).*test', r'.*\/junit\/')
1471 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491472 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231473 )
1474 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1475 local_path = f.LocalPath()
1476 is_inside_javadoc = False
1477 for line_number, line in f.ChangedContents():
1478 if is_inside_javadoc and javadoc_end_re.search(line):
1479 is_inside_javadoc = False
1480 if not is_inside_javadoc and javadoc_start_re.search(line):
1481 is_inside_javadoc = True
1482 if is_inside_javadoc:
1483 continue
1484 if (inclusion_re.search(line) and
1485 not comment_re.search(line) and
1486 not exclusion_re.search(line)):
1487 problems.append(
1488 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1489
1490 if problems:
1491 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1492 else:
1493 return []
1494
1495
[email protected]10689ca2011-09-02 02:31:541496def _CheckNoIOStreamInHeaders(input_api, output_api):
1497 """Checks to make sure no .h files include <iostream>."""
1498 files = []
1499 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1500 input_api.re.MULTILINE)
1501 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1502 if not f.LocalPath().endswith('.h'):
1503 continue
1504 contents = input_api.ReadFile(f)
1505 if pattern.search(contents):
1506 files.append(f)
1507
1508 if len(files):
yolandyandaabc6d2016-04-18 18:29:391509 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061510 'Do not #include <iostream> in header files, since it inserts static '
1511 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541512 '#include <ostream>. See http://crbug.com/94794',
1513 files) ]
1514 return []
1515
Danil Chapovalov3518f362018-08-11 16:13:431516def _CheckNoStrCatRedefines(input_api, output_api):
1517 """Checks no windows headers with StrCat redefined are included directly."""
1518 files = []
1519 pattern_deny = input_api.re.compile(
1520 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1521 input_api.re.MULTILINE)
1522 pattern_allow = input_api.re.compile(
1523 r'^#include\s"base/win/windows_defines.inc"',
1524 input_api.re.MULTILINE)
1525 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1526 contents = input_api.ReadFile(f)
1527 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1528 files.append(f.LocalPath())
1529
1530 if len(files):
1531 return [output_api.PresubmitError(
1532 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1533 'directly since they pollute code with StrCat macro. Instead, '
1534 'include matching header from base/win. See http://crbug.com/856536',
1535 files) ]
1536 return []
1537
[email protected]10689ca2011-09-02 02:31:541538
[email protected]72df4e782012-06-21 16:28:181539def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521540 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181541 problems = []
1542 for f in input_api.AffectedFiles():
1543 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1544 continue
1545
1546 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041547 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181548 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1549
1550 if not problems:
1551 return []
1552 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1553 '\n'.join(problems))]
1554
Dominic Battre033531052018-09-24 15:45:341555def _CheckNoDISABLETypoInTests(input_api, output_api):
1556 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1557
1558 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1559 instead of DISABLED_. To filter false positives, reports are only generated
1560 if a corresponding MAYBE_ line exists.
1561 """
1562 problems = []
1563
1564 # The following two patterns are looked for in tandem - is a test labeled
1565 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1566 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1567 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1568
1569 # This is for the case that a test is disabled on all platforms.
1570 full_disable_pattern = input_api.re.compile(
1571 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1572 input_api.re.MULTILINE)
1573
Katie Df13948e2018-09-25 07:33:441574 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341575 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1576 continue
1577
1578 # Search for MABYE_, DISABLE_ pairs.
1579 disable_lines = {} # Maps of test name to line number.
1580 maybe_lines = {}
1581 for line_num, line in f.ChangedContents():
1582 disable_match = disable_pattern.search(line)
1583 if disable_match:
1584 disable_lines[disable_match.group(1)] = line_num
1585 maybe_match = maybe_pattern.search(line)
1586 if maybe_match:
1587 maybe_lines[maybe_match.group(1)] = line_num
1588
1589 # Search for DISABLE_ occurrences within a TEST() macro.
1590 disable_tests = set(disable_lines.keys())
1591 maybe_tests = set(maybe_lines.keys())
1592 for test in disable_tests.intersection(maybe_tests):
1593 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1594
1595 contents = input_api.ReadFile(f)
1596 full_disable_match = full_disable_pattern.search(contents)
1597 if full_disable_match:
1598 problems.append(' %s' % f.LocalPath())
1599
1600 if not problems:
1601 return []
1602 return [
1603 output_api.PresubmitPromptWarning(
1604 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1605 '\n'.join(problems))
1606 ]
1607
[email protected]72df4e782012-06-21 16:28:181608
danakj61c1aa22015-10-26 19:55:521609def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571610 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521611 errors = []
1612 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1613 input_api.re.MULTILINE)
1614 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1615 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1616 continue
1617 for lnum, line in f.ChangedContents():
1618 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171619 errors.append(output_api.PresubmitError(
1620 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571621 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171622 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521623 return errors
1624
1625
Makoto Shimazu3ad422cd2019-05-08 02:35:141626def _FindHistogramNameInChunk(histogram_name, chunk):
1627 """Tries to find a histogram name or prefix in a line.
1628
1629 Returns the existence of the histogram name, or None if it needs more chunk
1630 to determine."""
mcasasb7440c282015-02-04 14:52:191631 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1632 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141633 if '<affected-histogram' in chunk:
1634 # If the tag is not completed, needs more chunk to get the name.
1635 if not '>' in chunk:
1636 return None
1637 if not 'name="' in chunk:
1638 return False
1639 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1640 # expect the only attribute is the name.
1641 histogram_prefix = chunk.split('"')[1]
1642 return histogram_prefix in histogram_name
1643 # Typically the whole histogram name should in the line.
1644 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191645
1646
1647def _CheckUmaHistogramChanges(input_api, output_api):
1648 """Check that UMA histogram names in touched lines can still be found in other
1649 lines of the patch or in histograms.xml. Note that this check would not catch
1650 the reverse: changes in histograms.xml not matched in the code itself."""
1651 touched_histograms = []
1652 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471653 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1654 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1655 name_pattern = r'"(.*?)"'
1656 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1657 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1658 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1659 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1660 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171661 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191662 for f in input_api.AffectedFiles():
1663 # If histograms.xml itself is modified, keep the modified lines for later.
1664 if f.LocalPath().endswith(('histograms.xml')):
1665 histograms_xml_modifications = f.ChangedContents()
1666 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471667 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1668 single_line_re = single_line_c_re
1669 split_line_prefix_re = split_line_c_prefix_re
1670 elif f.LocalPath().endswith(('java')):
1671 single_line_re = single_line_java_re
1672 split_line_prefix_re = split_line_java_prefix_re
1673 else:
mcasasb7440c282015-02-04 14:52:191674 continue
1675 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171676 if last_line_matched_prefix:
1677 suffix_found = split_line_suffix_re.search(line)
1678 if suffix_found :
1679 touched_histograms.append([suffix_found.group(1), f, line_num])
1680 last_line_matched_prefix = False
1681 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061682 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191683 if found:
1684 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171685 continue
1686 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191687
1688 # Search for the touched histogram names in the local modifications to
1689 # histograms.xml, and, if not found, on the base histograms.xml file.
1690 unmatched_histograms = []
1691 for histogram_info in touched_histograms:
1692 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141693 chunk = ''
mcasasb7440c282015-02-04 14:52:191694 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141695 chunk += line
1696 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1697 if histogram_name_found is None:
1698 continue
1699 chunk = ''
mcasasb7440c282015-02-04 14:52:191700 if histogram_name_found:
1701 break
1702 if not histogram_name_found:
1703 unmatched_histograms.append(histogram_info)
1704
eromanb90c82e7e32015-04-01 15:13:491705 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191706 problems = []
1707 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491708 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191709 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451710 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191711 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141712 chunk = ''
mcasasb7440c282015-02-04 14:52:191713 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141714 chunk += line
1715 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1716 chunk)
1717 if histogram_name_found is None:
1718 continue
1719 chunk = ''
mcasasb7440c282015-02-04 14:52:191720 if histogram_name_found:
1721 break
1722 if not histogram_name_found:
1723 problems.append(' [%s:%d] %s' %
1724 (f.LocalPath(), line_num, histogram_name))
1725
1726 if not problems:
1727 return []
1728 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1729 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491730 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191731
wnwenbdc444e2016-05-25 13:44:151732
yolandyandaabc6d2016-04-18 18:29:391733def _CheckFlakyTestUsage(input_api, output_api):
1734 """Check that FlakyTest annotation is our own instead of the android one"""
1735 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1736 files = []
1737 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1738 if f.LocalPath().endswith('Test.java'):
1739 if pattern.search(input_api.ReadFile(f)):
1740 files.append(f)
1741 if len(files):
1742 return [output_api.PresubmitError(
1743 'Use org.chromium.base.test.util.FlakyTest instead of '
1744 'android.test.FlakyTest',
1745 files)]
1746 return []
mcasasb7440c282015-02-04 14:52:191747
wnwenbdc444e2016-05-25 13:44:151748
[email protected]8ea5d4b2011-09-13 21:49:221749def _CheckNoNewWStrings(input_api, output_api):
1750 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271751 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221752 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201753 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571754 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341755 '/win/' in f.LocalPath() or
1756 'chrome_elf' in f.LocalPath() or
1757 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201758 continue
[email protected]8ea5d4b2011-09-13 21:49:221759
[email protected]a11dbe9b2012-08-07 01:32:581760 allowWString = False
[email protected]b5c24292011-11-28 14:38:201761 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581762 if 'presubmit: allow wstring' in line:
1763 allowWString = True
1764 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271765 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581766 allowWString = False
1767 else:
1768 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221769
[email protected]55463aa62011-10-12 00:48:271770 if not problems:
1771 return []
1772 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581773 ' If you are calling a cross-platform API that accepts a wstring, '
1774 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271775 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221776
1777
[email protected]2a8ac9c2011-10-19 17:20:441778def _CheckNoDEPSGIT(input_api, output_api):
1779 """Make sure .DEPS.git is never modified manually."""
1780 if any(f.LocalPath().endswith('.DEPS.git') for f in
1781 input_api.AffectedFiles()):
1782 return [output_api.PresubmitError(
1783 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1784 'automated system based on what\'s in DEPS and your changes will be\n'
1785 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501786 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1787 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441788 'for more information')]
1789 return []
1790
1791
tandriief664692014-09-23 14:51:471792def _CheckValidHostsInDEPS(input_api, output_api):
1793 """Checks that DEPS file deps are from allowed_hosts."""
1794 # Run only if DEPS file has been modified to annoy fewer bystanders.
1795 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1796 return []
1797 # Outsource work to gclient verify
1798 try:
John Budorickf20c0042019-04-25 23:23:401799 gclient_path = input_api.os_path.join(
1800 input_api.PresubmitLocalPath(),
1801 'third_party', 'depot_tools', 'gclient.py')
1802 input_api.subprocess.check_output(
1803 [input_api.python_executable, gclient_path, 'verify'],
1804 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471805 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201806 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471807 return [output_api.PresubmitError(
1808 'DEPS file must have only git dependencies.',
1809 long_text=error.output)]
1810
1811
Mario Sanchez Prada2472cab2019-09-18 10:58:311812def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1813 type_name, message):
1814 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1815
1816 Returns an string composed of the name of the file, the line number where the
1817 match has been found and the additional text passed as |message| in case the
1818 target type name matches the text inside the line passed as parameter.
1819 """
1820 matched = False
1821 if type_name[0:1] == '/':
1822 regex = type_name[1:]
1823 if input_api.re.search(regex, line):
1824 matched = True
1825 elif type_name in line:
1826 matched = True
1827
1828 result = []
1829 if matched:
1830 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1831 for message_line in message:
1832 result.append(' %s' % message_line)
1833
1834 return result
1835
1836
[email protected]127f18ec2012-06-16 05:05:591837def _CheckNoBannedFunctions(input_api, output_api):
1838 """Make sure that banned functions are not used."""
1839 warnings = []
1840 errors = []
1841
wnwenbdc444e2016-05-25 13:44:151842 def IsBlacklisted(affected_file, blacklist):
1843 local_path = affected_file.LocalPath()
1844 for item in blacklist:
1845 if input_api.re.match(item, local_path):
1846 return True
1847 return False
1848
Peter K. Lee6c03ccff2019-07-15 14:40:051849 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541850 local_path = affected_file.LocalPath()
1851 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1852 return False
1853 basename = input_api.os_path.basename(local_path)
1854 if 'ios' in basename.split('_'):
1855 return True
1856 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1857 if sep and 'ios' in local_path.split(sep):
1858 return True
1859 return False
1860
wnwenbdc444e2016-05-25 13:44:151861 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311862 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1863 func_name, message)
1864 if problems:
wnwenbdc444e2016-05-25 13:44:151865 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311866 errors.extend(problems)
1867 else:
1868 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151869
Eric Stevensona9a980972017-09-23 00:04:411870 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1871 for f in input_api.AffectedFiles(file_filter=file_filter):
1872 for line_num, line in f.ChangedContents():
1873 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1874 CheckForMatch(f, line_num, line, func_name, message, error)
1875
[email protected]127f18ec2012-06-16 05:05:591876 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1877 for f in input_api.AffectedFiles(file_filter=file_filter):
1878 for line_num, line in f.ChangedContents():
1879 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151880 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591881
Peter K. Lee6c03ccff2019-07-15 14:40:051882 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541883 for line_num, line in f.ChangedContents():
1884 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1885 CheckForMatch(f, line_num, line, func_name, message, error)
1886
Peter K. Lee6c03ccff2019-07-15 14:40:051887 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1888 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1889 for line_num, line in f.ChangedContents():
1890 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1891 CheckForMatch(f, line_num, line, func_name, message, error)
1892
[email protected]127f18ec2012-06-16 05:05:591893 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1894 for f in input_api.AffectedFiles(file_filter=file_filter):
1895 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491896 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491897 if IsBlacklisted(f, excluded_paths):
1898 continue
wnwenbdc444e2016-05-25 13:44:151899 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591900
1901 result = []
1902 if (warnings):
1903 result.append(output_api.PresubmitPromptWarning(
1904 'Banned functions were used.\n' + '\n'.join(warnings)))
1905 if (errors):
1906 result.append(output_api.PresubmitError(
1907 'Banned functions were used.\n' + '\n'.join(errors)))
1908 return result
1909
1910
Michael Thiessen44457642020-02-06 00:24:151911def _CheckAndroidNoBannedImports(input_api, output_api):
1912 """Make sure that banned java imports are not used."""
1913 errors = []
1914
1915 def IsException(path, exceptions):
1916 for exception in exceptions:
1917 if (path.startswith(exception)):
1918 return True
1919 return False
1920
1921 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1922 for f in input_api.AffectedFiles(file_filter=file_filter):
1923 for line_num, line in f.ChangedContents():
1924 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1925 if IsException(f.LocalPath(), exceptions):
1926 continue;
1927 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1928 'import ' + import_name, message)
1929 if problems:
1930 errors.extend(problems)
1931 result = []
1932 if (errors):
1933 result.append(output_api.PresubmitError(
1934 'Banned imports were used.\n' + '\n'.join(errors)))
1935 return result
1936
1937
Mario Sanchez Prada2472cab2019-09-18 10:58:311938def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1939 """Make sure that old Mojo types are not used."""
1940 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571941 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311942
Mario Sanchez Pradaaab91382019-12-19 08:57:091943 # For any path that is not an "ok" or an "error" path, a warning will be
1944 # raised if deprecated mojo types are found.
1945 ok_paths = ['components/arc']
1946 error_paths = ['third_party/blink', 'content']
1947
Mario Sanchez Prada2472cab2019-09-18 10:58:311948 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1949 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571950 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091951 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311952 continue
1953
1954 for line_num, line in f.ChangedContents():
1955 for func_name, message in _DEPRECATED_MOJO_TYPES:
1956 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1957 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571958
Mario Sanchez Prada2472cab2019-09-18 10:58:311959 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091960 # Raise errors inside |error_paths| and warnings everywhere else.
1961 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571962 errors.extend(problems)
1963 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311964 warnings.extend(problems)
1965
1966 result = []
1967 if (warnings):
1968 result.append(output_api.PresubmitPromptWarning(
1969 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571970 if (errors):
1971 result.append(output_api.PresubmitError(
1972 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311973 return result
1974
1975
[email protected]6c063c62012-07-11 19:11:061976def _CheckNoPragmaOnce(input_api, output_api):
1977 """Make sure that banned functions are not used."""
1978 files = []
1979 pattern = input_api.re.compile(r'^#pragma\s+once',
1980 input_api.re.MULTILINE)
1981 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1982 if not f.LocalPath().endswith('.h'):
1983 continue
1984 contents = input_api.ReadFile(f)
1985 if pattern.search(contents):
1986 files.append(f)
1987
1988 if files:
1989 return [output_api.PresubmitError(
1990 'Do not use #pragma once in header files.\n'
1991 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1992 files)]
1993 return []
1994
[email protected]127f18ec2012-06-16 05:05:591995
[email protected]e7479052012-09-19 00:26:121996def _CheckNoTrinaryTrueFalse(input_api, output_api):
1997 """Checks to make sure we don't introduce use of foo ? true : false."""
1998 problems = []
1999 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2000 for f in input_api.AffectedFiles():
2001 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2002 continue
2003
2004 for line_num, line in f.ChangedContents():
2005 if pattern.match(line):
2006 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2007
2008 if not problems:
2009 return []
2010 return [output_api.PresubmitPromptWarning(
2011 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2012 '\n'.join(problems))]
2013
2014
[email protected]55f9f382012-07-31 11:02:182015def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282016 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182017 change. Breaking - rules is an error, breaking ! rules is a
2018 warning.
2019 """
mohan.reddyf21db962014-10-16 12:26:472020 import sys
[email protected]55f9f382012-07-31 11:02:182021 # We need to wait until we have an input_api object and use this
2022 # roundabout construct to import checkdeps because this file is
2023 # eval-ed and thus doesn't have __file__.
2024 original_sys_path = sys.path
2025 try:
2026 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472027 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182028 import checkdeps
[email protected]55f9f382012-07-31 11:02:182029 from rules import Rule
2030 finally:
2031 # Restore sys.path to what it was before.
2032 sys.path = original_sys_path
2033
2034 added_includes = []
rhalavati08acd232017-04-03 07:23:282035 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242036 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182037 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062038 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502039 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082040 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062041 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502042 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082043 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062044 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502045 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082046 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182047
[email protected]26385172013-05-09 23:11:352048 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182049
2050 error_descriptions = []
2051 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282052 error_subjects = set()
2053 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182054 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2055 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082056 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182057 description_with_path = '%s\n %s' % (path, rule_description)
2058 if rule_type == Rule.DISALLOW:
2059 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282060 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182061 else:
2062 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282063 warning_subjects.add("#includes")
2064
2065 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2066 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082067 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282068 description_with_path = '%s\n %s' % (path, rule_description)
2069 if rule_type == Rule.DISALLOW:
2070 error_descriptions.append(description_with_path)
2071 error_subjects.add("imports")
2072 else:
2073 warning_descriptions.append(description_with_path)
2074 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182075
Jinsuk Kim5a092672017-10-24 22:42:242076 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022077 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082078 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242079 description_with_path = '%s\n %s' % (path, rule_description)
2080 if rule_type == Rule.DISALLOW:
2081 error_descriptions.append(description_with_path)
2082 error_subjects.add("imports")
2083 else:
2084 warning_descriptions.append(description_with_path)
2085 warning_subjects.add("imports")
2086
[email protected]55f9f382012-07-31 11:02:182087 results = []
2088 if error_descriptions:
2089 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282090 'You added one or more %s that violate checkdeps rules.'
2091 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182092 error_descriptions))
2093 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422094 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282095 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182096 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282097 '%s? See relevant DEPS file(s) for details and contacts.' %
2098 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182099 warning_descriptions))
2100 return results
2101
2102
[email protected]fbcafe5a2012-08-08 15:31:222103def _CheckFilePermissions(input_api, output_api):
2104 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152105 if input_api.platform == 'win32':
2106 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292107 checkperms_tool = input_api.os_path.join(
2108 input_api.PresubmitLocalPath(),
2109 'tools', 'checkperms', 'checkperms.py')
2110 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472111 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392112 with input_api.CreateTemporaryFile() as file_list:
2113 for f in input_api.AffectedFiles():
2114 # checkperms.py file/directory arguments must be relative to the
2115 # repository.
2116 file_list.write(f.LocalPath() + '\n')
2117 file_list.close()
2118 args += ['--file-list', file_list.name]
2119 try:
2120 input_api.subprocess.check_output(args)
2121 return []
2122 except input_api.subprocess.CalledProcessError as error:
2123 return [output_api.PresubmitError(
2124 'checkperms.py failed:',
2125 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222126
2127
robertocn832f5992017-01-04 19:01:302128def _CheckTeamTags(input_api, output_api):
2129 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2130 checkteamtags_tool = input_api.os_path.join(
2131 input_api.PresubmitLocalPath(),
2132 'tools', 'checkteamtags', 'checkteamtags.py')
2133 args = [input_api.python_executable, checkteamtags_tool,
2134 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222135 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302136 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2137 'OWNERS']
2138 try:
2139 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052140 warnings = input_api.subprocess.check_output(args + files).splitlines()
2141 if warnings:
2142 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302143 return []
2144 except input_api.subprocess.CalledProcessError as error:
2145 return [output_api.PresubmitError(
2146 'checkteamtags.py failed:',
2147 long_text=error.output)]
2148
2149
[email protected]c8278b32012-10-30 20:35:492150def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2151 """Makes sure we don't include ui/aura/window_property.h
2152 in header files.
2153 """
2154 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2155 errors = []
2156 for f in input_api.AffectedFiles():
2157 if not f.LocalPath().endswith('.h'):
2158 continue
2159 for line_num, line in f.ChangedContents():
2160 if pattern.match(line):
2161 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2162
2163 results = []
2164 if errors:
2165 results.append(output_api.PresubmitError(
2166 'Header files should not include ui/aura/window_property.h', errors))
2167 return results
2168
2169
[email protected]70ca77752012-11-20 03:45:032170def _CheckForVersionControlConflictsInFile(input_api, f):
2171 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2172 errors = []
2173 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162174 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232175 # First-level headers in markdown look a lot like version control
2176 # conflict markers. http://daringfireball.net/projects/markdown/basics
2177 continue
[email protected]70ca77752012-11-20 03:45:032178 if pattern.match(line):
2179 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2180 return errors
2181
2182
2183def _CheckForVersionControlConflicts(input_api, output_api):
2184 """Usually this is not intentional and will cause a compile failure."""
2185 errors = []
2186 for f in input_api.AffectedFiles():
2187 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2188
2189 results = []
2190 if errors:
2191 results.append(output_api.PresubmitError(
2192 'Version control conflict markers found, please resolve.', errors))
2193 return results
2194
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202195
estadee17314a02017-01-12 16:22:162196def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2197 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2198 errors = []
2199 for f in input_api.AffectedFiles():
2200 for line_num, line in f.ChangedContents():
2201 if pattern.search(line):
2202 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2203
2204 results = []
2205 if errors:
2206 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502207 'Found Google support URL addressed by answer number. Please replace '
2208 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162209 return results
2210
[email protected]70ca77752012-11-20 03:45:032211
[email protected]06e6d0ff2012-12-11 01:36:442212def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2213 def FilterFile(affected_file):
2214 """Filter function for use with input_api.AffectedSourceFiles,
2215 below. This filters out everything except non-test files from
2216 top-level directories that generally speaking should not hard-code
2217 service URLs (e.g. src/android_webview/, src/content/ and others).
2218 """
2219 return input_api.FilterSourceFile(
2220 affected_file,
Egor Paskoce145c42018-09-28 19:31:042221 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442222 black_list=(_EXCLUDED_PATHS +
2223 _TEST_CODE_EXCLUDED_PATHS +
2224 input_api.DEFAULT_BLACK_LIST))
2225
reillyi38965732015-11-16 18:27:332226 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2227 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462228 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2229 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442230 problems = [] # items are (filename, line_number, line)
2231 for f in input_api.AffectedSourceFiles(FilterFile):
2232 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462233 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442234 problems.append((f.LocalPath(), line_num, line))
2235
2236 if problems:
[email protected]f7051d52013-04-02 18:31:422237 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442238 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582239 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442240 [' %s:%d: %s' % (
2241 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032242 else:
2243 return []
[email protected]06e6d0ff2012-12-11 01:36:442244
2245
James Cook6b6597c2019-11-06 22:05:292246def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2247 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2248 def FileFilter(affected_file):
2249 """Includes directories known to be Chrome OS only."""
2250 return input_api.FilterSourceFile(
2251 affected_file,
2252 white_list=('^ash/',
2253 '^chromeos/', # Top-level src/chromeos.
2254 '/chromeos/', # Any path component.
2255 '^components/arc',
2256 '^components/exo'),
2257 black_list=(input_api.DEFAULT_BLACK_LIST))
2258
2259 prefs = []
2260 priority_prefs = []
2261 for f in input_api.AffectedFiles(file_filter=FileFilter):
2262 for line_num, line in f.ChangedContents():
2263 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2264 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2265 prefs.append(' %s' % line)
2266 if input_api.re.search(
2267 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2268 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2269 priority_prefs.append(' %s' % line)
2270
2271 results = []
2272 if (prefs):
2273 results.append(output_api.PresubmitPromptWarning(
2274 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2275 'by browser sync settings. If these prefs should be controlled by OS '
2276 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2277 if (priority_prefs):
2278 results.append(output_api.PresubmitPromptWarning(
2279 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2280 'controlled by browser sync settings. If these prefs should be '
2281 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2282 'instead.\n' + '\n'.join(prefs)))
2283 return results
2284
2285
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492286# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272287def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2288 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312289 The native_client_sdk directory is excluded because it has auto-generated PNG
2290 files for documentation.
[email protected]d2530012013-01-25 16:39:272291 """
[email protected]d2530012013-01-25 16:39:272292 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492293 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042294 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312295 file_filter = lambda f: input_api.FilterSourceFile(
2296 f, white_list=white_list, black_list=black_list)
2297 for f in input_api.AffectedFiles(include_deletes=False,
2298 file_filter=file_filter):
2299 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272300
2301 results = []
2302 if errors:
2303 results.append(output_api.PresubmitError(
2304 'The name of PNG files should not have abbreviations. \n'
2305 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2306 'Contact [email protected] if you have questions.', errors))
2307 return results
2308
2309
Daniel Cheng4dcdb6b2017-04-13 08:30:172310def _ExtractAddRulesFromParsedDeps(parsed_deps):
2311 """Extract the rules that add dependencies from a parsed DEPS file.
2312
2313 Args:
2314 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2315 add_rules = set()
2316 add_rules.update([
2317 rule[1:] for rule in parsed_deps.get('include_rules', [])
2318 if rule.startswith('+') or rule.startswith('!')
2319 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502320 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172321 {}).iteritems():
2322 add_rules.update([
2323 rule[1:] for rule in rules
2324 if rule.startswith('+') or rule.startswith('!')
2325 ])
2326 return add_rules
2327
2328
2329def _ParseDeps(contents):
2330 """Simple helper for parsing DEPS files."""
2331 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172332 class _VarImpl:
2333
2334 def __init__(self, local_scope):
2335 self._local_scope = local_scope
2336
2337 def Lookup(self, var_name):
2338 """Implements the Var syntax."""
2339 try:
2340 return self._local_scope['vars'][var_name]
2341 except KeyError:
2342 raise Exception('Var is not defined: %s' % var_name)
2343
2344 local_scope = {}
2345 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172346 'Var': _VarImpl(local_scope).Lookup,
2347 }
2348 exec contents in global_scope, local_scope
2349 return local_scope
2350
2351
2352def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082353 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412354 a set of DEPS entries that we should look up.
2355
2356 For a directory (rather than a specific filename) we fake a path to
2357 a specific filename by adding /DEPS. This is chosen as a file that
2358 will seldom or never be subject to per-file include_rules.
2359 """
[email protected]2b438d62013-11-14 17:54:142360 # We ignore deps entries on auto-generated directories.
2361 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082362
Daniel Cheng4dcdb6b2017-04-13 08:30:172363 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2364 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2365
2366 added_deps = new_deps.difference(old_deps)
2367
[email protected]2b438d62013-11-14 17:54:142368 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172369 for added_dep in added_deps:
2370 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2371 continue
2372 # Assume that a rule that ends in .h is a rule for a specific file.
2373 if added_dep.endswith('.h'):
2374 results.add(added_dep)
2375 else:
2376 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082377 return results
2378
2379
[email protected]e871964c2013-05-13 14:14:552380def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2381 """When a dependency prefixed with + is added to a DEPS file, we
2382 want to make sure that the change is reviewed by an OWNER of the
2383 target file or directory, to avoid layering violations from being
2384 introduced. This check verifies that this happens.
2385 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172386 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242387
2388 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492389 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242390 for f in input_api.AffectedFiles(include_deletes=False,
2391 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552392 filename = input_api.os_path.basename(f.LocalPath())
2393 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172394 virtual_depended_on_files.update(_CalculateAddedDeps(
2395 input_api.os_path,
2396 '\n'.join(f.OldContents()),
2397 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552398
[email protected]e871964c2013-05-13 14:14:552399 if not virtual_depended_on_files:
2400 return []
2401
2402 if input_api.is_committing:
2403 if input_api.tbr:
2404 return [output_api.PresubmitNotifyResult(
2405 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272406 if input_api.dry_run:
2407 return [output_api.PresubmitNotifyResult(
2408 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552409 if not input_api.change.issue:
2410 return [output_api.PresubmitError(
2411 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402412 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552413 output = output_api.PresubmitError
2414 else:
2415 output = output_api.PresubmitNotifyResult
2416
2417 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502418 owner_email, reviewers = (
2419 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2420 input_api,
2421 owners_db.email_regexp,
2422 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552423
2424 owner_email = owner_email or input_api.change.author_email
2425
[email protected]de4f7d22013-05-23 14:27:462426 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512427 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462428 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552429 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2430 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412431
2432 # We strip the /DEPS part that was added by
2433 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2434 # directory.
2435 def StripDeps(path):
2436 start_deps = path.rfind('/DEPS')
2437 if start_deps != -1:
2438 return path[:start_deps]
2439 else:
2440 return path
2441 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552442 for path in missing_files]
2443
2444 if unapproved_dependencies:
2445 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152446 output('You need LGTM from owners of depends-on paths in DEPS that were '
2447 'modified in this CL:\n %s' %
2448 '\n '.join(sorted(unapproved_dependencies)))]
2449 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2450 output_list.append(output(
2451 'Suggested missing target path OWNERS:\n %s' %
2452 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552453 return output_list
2454
2455 return []
2456
2457
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492458# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402459def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492460 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402461 black_list = (_EXCLUDED_PATHS +
2462 _TEST_CODE_EXCLUDED_PATHS +
2463 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042464 (r"^base[\\/]logging\.h$",
2465 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222466 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042467 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2468 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2469 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122470 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182471 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152472 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032473 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152474 r"^chrome[\\/]chrome_cleaner[\\/].*",
2475 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2476 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042477 r"^chromecast[\\/]",
2478 r"^cloud_print[\\/]",
2479 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482480 r"dump_stability_report_main_win.cc$",
Sharon Yang5ee61d7e2020-04-15 23:39:052481 r"^components[\\/]media_control[\\/]renderer[\\/]"
2482 r"media_playback_options\.cc$",
Egor Paskoce145c42018-09-28 19:31:042483 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462484 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042485 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462486 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042487 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252488 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042489 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2490 r"^courgette[\\/]courgette_tool\.cc$",
2491 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272492 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002493 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332494 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042495 r"^ipc[\\/]ipc_logging\.cc$",
2496 r"^native_client_sdk[\\/]",
2497 r"^remoting[\\/]base[\\/]logging\.h$",
2498 r"^remoting[\\/]host[\\/].*",
2499 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062500 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332501 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042502 r"^tools[\\/]",
2503 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2504 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332505 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402506 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492507 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402508
thomasanderson625d3932017-03-29 07:16:582509 log_info = set([])
2510 printf = set([])
[email protected]85218562013-11-22 07:41:402511
2512 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582513 for _, line in f.ChangedContents():
2514 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2515 log_info.add(f.LocalPath())
2516 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2517 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372518
thomasanderson625d3932017-03-29 07:16:582519 if input_api.re.search(r"\bprintf\(", line):
2520 printf.add(f.LocalPath())
2521 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2522 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402523
2524 if log_info:
2525 return [output_api.PresubmitError(
2526 'These files spam the console log with LOG(INFO):',
2527 items=log_info)]
2528 if printf:
2529 return [output_api.PresubmitError(
2530 'These files spam the console log with printf/fprintf:',
2531 items=printf)]
2532 return []
2533
2534
[email protected]49aa76a2013-12-04 06:59:162535def _CheckForAnonymousVariables(input_api, output_api):
2536 """These types are all expected to hold locks while in scope and
2537 so should never be anonymous (which causes them to be immediately
2538 destroyed)."""
2539 they_who_must_be_named = [
2540 'base::AutoLock',
2541 'base::AutoReset',
2542 'base::AutoUnlock',
2543 'SkAutoAlphaRestore',
2544 'SkAutoBitmapShaderInstall',
2545 'SkAutoBlitterChoose',
2546 'SkAutoBounderCommit',
2547 'SkAutoCallProc',
2548 'SkAutoCanvasRestore',
2549 'SkAutoCommentBlock',
2550 'SkAutoDescriptor',
2551 'SkAutoDisableDirectionCheck',
2552 'SkAutoDisableOvalCheck',
2553 'SkAutoFree',
2554 'SkAutoGlyphCache',
2555 'SkAutoHDC',
2556 'SkAutoLockColors',
2557 'SkAutoLockPixels',
2558 'SkAutoMalloc',
2559 'SkAutoMaskFreeImage',
2560 'SkAutoMutexAcquire',
2561 'SkAutoPathBoundsUpdate',
2562 'SkAutoPDFRelease',
2563 'SkAutoRasterClipValidate',
2564 'SkAutoRef',
2565 'SkAutoTime',
2566 'SkAutoTrace',
2567 'SkAutoUnref',
2568 ]
2569 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2570 # bad: base::AutoLock(lock.get());
2571 # not bad: base::AutoLock lock(lock.get());
2572 bad_pattern = input_api.re.compile(anonymous)
2573 # good: new base::AutoLock(lock.get())
2574 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2575 errors = []
2576
2577 for f in input_api.AffectedFiles():
2578 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2579 continue
2580 for linenum, line in f.ChangedContents():
2581 if bad_pattern.search(line) and not good_pattern.search(line):
2582 errors.append('%s:%d' % (f.LocalPath(), linenum))
2583
2584 if errors:
2585 return [output_api.PresubmitError(
2586 'These lines create anonymous variables that need to be named:',
2587 items=errors)]
2588 return []
2589
2590
Peter Kasting4844e46e2018-02-23 07:27:102591def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532592 # Returns whether |template_str| is of the form <T, U...> for some types T
2593 # and U. Assumes that |template_str| is already in the form <...>.
2594 def HasMoreThanOneArg(template_str):
2595 # Level of <...> nesting.
2596 nesting = 0
2597 for c in template_str:
2598 if c == '<':
2599 nesting += 1
2600 elif c == '>':
2601 nesting -= 1
2602 elif c == ',' and nesting == 1:
2603 return True
2604 return False
2605
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492606 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102607 sources = lambda affected_file: input_api.FilterSourceFile(
2608 affected_file,
2609 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2610 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492611 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552612
2613 # Pattern to capture a single "<...>" block of template arguments. It can
2614 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2615 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2616 # latter would likely require counting that < and > match, which is not
2617 # expressible in regular languages. Should the need arise, one can introduce
2618 # limited counting (matching up to a total number of nesting depth), which
2619 # should cover all practical cases for already a low nesting limit.
2620 template_arg_pattern = (
2621 r'<[^>]*' # Opening block of <.
2622 r'>([^<]*>)?') # Closing block of >.
2623 # Prefix expressing that whatever follows is not already inside a <...>
2624 # block.
2625 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102626 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552627 not_inside_template_arg_pattern
2628 + r'\bstd::unique_ptr'
2629 + template_arg_pattern
2630 + r'\(\)')
2631
2632 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2633 template_arg_no_array_pattern = (
2634 r'<[^>]*[^]]' # Opening block of <.
2635 r'>([^(<]*[^]]>)?') # Closing block of >.
2636 # Prefix saying that what follows is the start of an expression.
2637 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2638 # Suffix saying that what follows are call parentheses with a non-empty list
2639 # of arguments.
2640 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532641 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552642 return_construct_pattern = input_api.re.compile(
2643 start_of_expr_pattern
2644 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532645 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552646 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532647 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552648 + nonempty_arg_list_pattern)
2649
Vaclav Brozek851d9602018-04-04 16:13:052650 problems_constructor = []
2651 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102652 for f in input_api.AffectedSourceFiles(sources):
2653 for line_number, line in f.ChangedContents():
2654 # Disallow:
2655 # return std::unique_ptr<T>(foo);
2656 # bar = std::unique_ptr<T>(foo);
2657 # But allow:
2658 # return std::unique_ptr<T[]>(foo);
2659 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532660 # And also allow cases when the second template argument is present. Those
2661 # cases cannot be handled by std::make_unique:
2662 # return std::unique_ptr<T, U>(foo);
2663 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052664 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532665 return_construct_result = return_construct_pattern.search(line)
2666 if return_construct_result and not HasMoreThanOneArg(
2667 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052668 problems_constructor.append(
2669 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102670 # Disallow:
2671 # std::unique_ptr<T>()
2672 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052673 problems_nullptr.append(
2674 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2675
2676 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162677 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052678 errors.append(output_api.PresubmitError(
2679 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162680 problems_nullptr))
2681 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052682 errors.append(output_api.PresubmitError(
2683 'The following files use explicit std::unique_ptr constructor.'
2684 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162685 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102686 return errors
2687
2688
[email protected]999261d2014-03-03 20:08:082689def _CheckUserActionUpdate(input_api, output_api):
2690 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522691 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082692 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522693 # If actions.xml is already included in the changelist, the PRESUBMIT
2694 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082695 return []
2696
[email protected]999261d2014-03-03 20:08:082697 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2698 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522699 current_actions = None
[email protected]999261d2014-03-03 20:08:082700 for f in input_api.AffectedFiles(file_filter=file_filter):
2701 for line_num, line in f.ChangedContents():
2702 match = input_api.re.search(action_re, line)
2703 if match:
[email protected]2f92dec2014-03-07 19:21:522704 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2705 # loaded only once.
2706 if not current_actions:
2707 with open('tools/metrics/actions/actions.xml') as actions_f:
2708 current_actions = actions_f.read()
2709 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082710 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522711 action = 'name="{0}"'.format(action_name)
2712 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082713 return [output_api.PresubmitPromptWarning(
2714 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522715 'tools/metrics/actions/actions.xml. Please run '
2716 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082717 % (f.LocalPath(), line_num, action_name))]
2718 return []
2719
2720
Daniel Cheng13ca61a882017-08-25 15:11:252721def _ImportJSONCommentEater(input_api):
2722 import sys
2723 sys.path = sys.path + [input_api.os_path.join(
2724 input_api.PresubmitLocalPath(),
2725 'tools', 'json_comment_eater')]
2726 import json_comment_eater
2727 return json_comment_eater
2728
2729
[email protected]99171a92014-06-03 08:44:472730def _GetJSONParseError(input_api, filename, eat_comments=True):
2731 try:
2732 contents = input_api.ReadFile(filename)
2733 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252734 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132735 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472736
2737 input_api.json.loads(contents)
2738 except ValueError as e:
2739 return e
2740 return None
2741
2742
2743def _GetIDLParseError(input_api, filename):
2744 try:
2745 contents = input_api.ReadFile(filename)
2746 idl_schema = input_api.os_path.join(
2747 input_api.PresubmitLocalPath(),
2748 'tools', 'json_schema_compiler', 'idl_schema.py')
2749 process = input_api.subprocess.Popen(
2750 [input_api.python_executable, idl_schema],
2751 stdin=input_api.subprocess.PIPE,
2752 stdout=input_api.subprocess.PIPE,
2753 stderr=input_api.subprocess.PIPE,
2754 universal_newlines=True)
2755 (_, error) = process.communicate(input=contents)
2756 return error or None
2757 except ValueError as e:
2758 return e
2759
2760
2761def _CheckParseErrors(input_api, output_api):
2762 """Check that IDL and JSON files do not contain syntax errors."""
2763 actions = {
2764 '.idl': _GetIDLParseError,
2765 '.json': _GetJSONParseError,
2766 }
[email protected]99171a92014-06-03 08:44:472767 # Most JSON files are preprocessed and support comments, but these do not.
2768 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042769 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472770 ]
2771 # Only run IDL checker on files in these directories.
2772 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042773 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2774 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472775 ]
2776
2777 def get_action(affected_file):
2778 filename = affected_file.LocalPath()
2779 return actions.get(input_api.os_path.splitext(filename)[1])
2780
[email protected]99171a92014-06-03 08:44:472781 def FilterFile(affected_file):
2782 action = get_action(affected_file)
2783 if not action:
2784 return False
2785 path = affected_file.LocalPath()
2786
Erik Staab2dd72b12020-04-16 15:03:402787 if _MatchesFile(input_api,
2788 _KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS,
2789 path):
[email protected]99171a92014-06-03 08:44:472790 return False
2791
2792 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162793 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472794 return False
2795 return True
2796
2797 results = []
2798 for affected_file in input_api.AffectedFiles(
2799 file_filter=FilterFile, include_deletes=False):
2800 action = get_action(affected_file)
2801 kwargs = {}
2802 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162803 _MatchesFile(input_api, json_no_comments_patterns,
2804 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472805 kwargs['eat_comments'] = False
2806 parse_error = action(input_api,
2807 affected_file.AbsoluteLocalPath(),
2808 **kwargs)
2809 if parse_error:
2810 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2811 (affected_file.LocalPath(), parse_error)))
2812 return results
2813
2814
[email protected]760deea2013-12-10 19:33:492815def _CheckJavaStyle(input_api, output_api):
2816 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472817 import sys
[email protected]760deea2013-12-10 19:33:492818 original_sys_path = sys.path
2819 try:
2820 sys.path = sys.path + [input_api.os_path.join(
2821 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2822 import checkstyle
2823 finally:
2824 # Restore sys.path to what it was before.
2825 sys.path = original_sys_path
2826
2827 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092828 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512829 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492830
2831
Nate Fischerdfd9812e2019-07-18 22:03:002832def _CheckPythonDevilInit(input_api, output_api):
2833 """Checks to make sure devil is initialized correctly in python scripts."""
2834 script_common_initialize_pattern = input_api.re.compile(
2835 r'script_common\.InitializeEnvironment\(')
2836 devil_env_config_initialize = input_api.re.compile(
2837 r'devil_env\.config\.Initialize\(')
2838
2839 errors = []
2840
2841 sources = lambda affected_file: input_api.FilterSourceFile(
2842 affected_file,
2843 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2844 (r'^build[\\/]android[\\/]devil_chromium\.py',
2845 r'^third_party[\\/].*',)),
2846 white_list=[r'.*\.py$'])
2847
2848 for f in input_api.AffectedSourceFiles(sources):
2849 for line_num, line in f.ChangedContents():
2850 if (script_common_initialize_pattern.search(line) or
2851 devil_env_config_initialize.search(line)):
2852 errors.append("%s:%d" % (f.LocalPath(), line_num))
2853
2854 results = []
2855
2856 if errors:
2857 results.append(output_api.PresubmitError(
2858 'Devil initialization should always be done using '
2859 'devil_chromium.Initialize() in the chromium project, to use better '
2860 'defaults for dependencies (ex. up-to-date version of adb).',
2861 errors))
2862
2863 return results
2864
2865
Sean Kau46e29bc2017-08-28 16:31:162866def _MatchesFile(input_api, patterns, path):
2867 for pattern in patterns:
2868 if input_api.re.search(pattern, path):
2869 return True
2870 return False
2871
2872
Daniel Cheng7052cdf2017-11-21 19:23:292873def _GetOwnersFilesToCheckForIpcOwners(input_api):
2874 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172875
Daniel Cheng7052cdf2017-11-21 19:23:292876 Returns:
2877 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2878 contain to cover IPC-related files with noparent reviewer rules.
2879 """
2880 # Whether or not a file affects IPC is (mostly) determined by a simple list
2881 # of filename patterns.
dchenge07de812016-06-20 19:27:172882 file_patterns = [
palmerb19a0932017-01-24 04:00:312883 # Legacy IPC:
dchenge07de812016-06-20 19:27:172884 '*_messages.cc',
2885 '*_messages*.h',
2886 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312887 # Mojo IPC:
dchenge07de812016-06-20 19:27:172888 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472889 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172890 '*_struct_traits*.*',
2891 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312892 '*.typemap',
2893 # Android native IPC:
2894 '*.aidl',
2895 # Blink uses a different file naming convention:
2896 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472897 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172898 '*StructTraits*.*',
2899 '*TypeConverter*.*',
2900 ]
2901
scottmg7a6ed5ba2016-11-04 18:22:042902 # These third_party directories do not contain IPCs, but contain files
2903 # matching the above patterns, which trigger false positives.
2904 exclude_paths = [
2905 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162906 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232907 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292908 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542909 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162910 # These files are just used to communicate between class loaders running
2911 # in the same process.
2912 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572913 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2914
scottmg7a6ed5ba2016-11-04 18:22:042915 ]
2916
dchenge07de812016-06-20 19:27:172917 # Dictionary mapping an OWNERS file path to Patterns.
2918 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2919 # rules ) to a PatternEntry.
2920 # PatternEntry is a dictionary with two keys:
2921 # - 'files': the files that are matched by this pattern
2922 # - 'rules': the per-file rules needed for this pattern
2923 # For example, if we expect OWNERS file to contain rules for *.mojom and
2924 # *_struct_traits*.*, Patterns might look like this:
2925 # {
2926 # '*.mojom': {
2927 # 'files': ...,
2928 # 'rules': [
2929 # 'per-file *.mojom=set noparent',
2930 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2931 # ],
2932 # },
2933 # '*_struct_traits*.*': {
2934 # 'files': ...,
2935 # 'rules': [
2936 # 'per-file *_struct_traits*.*=set noparent',
2937 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2938 # ],
2939 # },
2940 # }
2941 to_check = {}
2942
Daniel Cheng13ca61a882017-08-25 15:11:252943 def AddPatternToCheck(input_file, pattern):
2944 owners_file = input_api.os_path.join(
2945 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2946 if owners_file not in to_check:
2947 to_check[owners_file] = {}
2948 if pattern not in to_check[owners_file]:
2949 to_check[owners_file][pattern] = {
2950 'files': [],
2951 'rules': [
2952 'per-file %s=set noparent' % pattern,
2953 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2954 ]
2955 }
Vaclav Brozekd5de76a2018-03-17 07:57:502956 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252957
dchenge07de812016-06-20 19:27:172958 # Iterate through the affected files to see what we actually need to check
2959 # for. We should only nag patch authors about per-file rules if a file in that
2960 # directory would match that pattern. If a directory only contains *.mojom
2961 # files and no *_messages*.h files, we should only nag about rules for
2962 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252963 for f in input_api.AffectedFiles(include_deletes=False):
Daniel Cheng76f49cc2020-04-21 01:48:262964 # Manifest files don't have a strong naming convention. Instead, try to find
2965 # affected .cc and .h files which look like they contain a manifest
2966 # definition.
2967 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2968 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2969 if (manifest_pattern.search(f.LocalPath()) and not
2970 test_manifest_pattern.search(f.LocalPath())):
2971 # We expect all actual service manifest files to contain at least one
2972 # qualified reference to service_manager::Manifest.
2973 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
Daniel Cheng13ca61a882017-08-25 15:11:252974 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172975 for pattern in file_patterns:
2976 if input_api.fnmatch.fnmatch(
2977 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042978 skip = False
2979 for exclude in exclude_paths:
2980 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2981 skip = True
2982 break
2983 if skip:
2984 continue
Daniel Cheng13ca61a882017-08-25 15:11:252985 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172986 break
2987
Daniel Cheng7052cdf2017-11-21 19:23:292988 return to_check
2989
2990
Wez17c66962020-04-29 15:26:032991def _AddOwnersFilesToCheckForFuchsiaSecurityOwners(input_api, to_check):
2992 """Adds OWNERS files to check for correct Fuchsia security owners."""
2993
2994 file_patterns = [
2995 # Component specifications.
2996 '*.cml', # Component Framework v2.
2997 '*.cmx', # Component Framework v1.
2998
2999 # Fuchsia IDL protocol specifications.
3000 '*.fidl',
3001 ]
3002
3003 def AddPatternToCheck(input_file, pattern):
3004 owners_file = input_api.os_path.join(
3005 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
3006 if owners_file not in to_check:
3007 to_check[owners_file] = {}
3008 if pattern not in to_check[owners_file]:
3009 to_check[owners_file][pattern] = {
3010 'files': [],
3011 'rules': [
3012 'per-file %s=set noparent' % pattern,
3013 'per-file %s=file://fuchsia/SECURITY_OWNERS' % pattern,
3014 ]
3015 }
3016 to_check[owners_file][pattern]['files'].append(input_file)
3017
3018 # Iterate through the affected files to see what we actually need to check
3019 # for. We should only nag patch authors about per-file rules if a file in that
3020 # directory would match that pattern.
3021 for f in input_api.AffectedFiles(include_deletes=False):
3022 for pattern in file_patterns:
3023 if input_api.fnmatch.fnmatch(
3024 input_api.os_path.basename(f.LocalPath()), pattern):
3025 AddPatternToCheck(f, pattern)
3026 break
3027
3028 return to_check
3029
3030
3031def _CheckSecurityOwners(input_api, output_api):
Daniel Cheng7052cdf2017-11-21 19:23:293032 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3033 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
Wez17c66962020-04-29 15:26:033034 _AddOwnersFilesToCheckForFuchsiaSecurityOwners(input_api, to_check)
Daniel Cheng7052cdf2017-11-21 19:23:293035
3036 if to_check:
3037 # If there are any OWNERS files to check, there are IPC-related changes in
3038 # this CL. Auto-CC the review list.
3039 output_api.AppendCC('[email protected]')
3040
3041 # Go through the OWNERS files to check, filtering out rules that are already
3042 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173043 for owners_file, patterns in to_check.iteritems():
3044 try:
3045 with file(owners_file) as f:
3046 lines = set(f.read().splitlines())
3047 for entry in patterns.itervalues():
3048 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3049 ]
3050 except IOError:
3051 # No OWNERS file, so all the rules are definitely missing.
3052 continue
3053
3054 # All the remaining lines weren't found in OWNERS files, so emit an error.
3055 errors = []
3056 for owners_file, patterns in to_check.iteritems():
3057 missing_lines = []
3058 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503059 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173060 missing_lines.extend(entry['rules'])
3061 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3062 if missing_lines:
3063 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053064 'Because of the presence of files:\n%s\n\n'
3065 '%s needs the following %d lines added:\n\n%s' %
3066 ('\n'.join(files), owners_file, len(missing_lines),
3067 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173068
3069 results = []
3070 if errors:
vabrf5ce3bf92016-07-11 14:52:413071 if input_api.is_committing:
3072 output = output_api.PresubmitError
3073 else:
3074 output = output_api.PresubmitPromptWarning
3075 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593076 'Found OWNERS files that need to be updated for IPC security ' +
3077 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173078 long_text='\n\n'.join(errors)))
3079
3080 return results
3081
3082
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263083def _CheckSetNoParent(input_api, output_api):
3084 """Checks that set noparent is only used together with an OWNERS file in
3085 //build/OWNERS.setnoparent (see also
3086 //docs/code_reviews.md#owners-files-details)
3087 """
3088 errors = []
3089
3090 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3091 allowed_owners_files = set()
3092 with open(allowed_owners_files_file, 'r') as f:
3093 for line in f:
3094 line = line.strip()
3095 if not line or line.startswith('#'):
3096 continue
3097 allowed_owners_files.add(line)
3098
3099 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3100
3101 for f in input_api.AffectedFiles(include_deletes=False):
3102 if not f.LocalPath().endswith('OWNERS'):
3103 continue
3104
3105 found_owners_files = set()
3106 found_set_noparent_lines = dict()
3107
3108 # Parse the OWNERS file.
3109 for lineno, line in enumerate(f.NewContents(), 1):
3110 line = line.strip()
3111 if line.startswith('set noparent'):
3112 found_set_noparent_lines[''] = lineno
3113 if line.startswith('file://'):
3114 if line in allowed_owners_files:
3115 found_owners_files.add('')
3116 if line.startswith('per-file'):
3117 match = per_file_pattern.match(line)
3118 if match:
3119 glob = match.group(1).strip()
3120 directive = match.group(2).strip()
3121 if directive == 'set noparent':
3122 found_set_noparent_lines[glob] = lineno
3123 if directive.startswith('file://'):
3124 if directive in allowed_owners_files:
3125 found_owners_files.add(glob)
3126
3127 # Check that every set noparent line has a corresponding file:// line
3128 # listed in build/OWNERS.setnoparent.
3129 for set_noparent_line in found_set_noparent_lines:
3130 if set_noparent_line in found_owners_files:
3131 continue
3132 errors.append(' %s:%d' % (f.LocalPath(),
3133 found_set_noparent_lines[set_noparent_line]))
3134
3135 results = []
3136 if errors:
3137 if input_api.is_committing:
3138 output = output_api.PresubmitError
3139 else:
3140 output = output_api.PresubmitPromptWarning
3141 results.append(output(
3142 'Found the following "set noparent" restrictions in OWNERS files that '
3143 'do not include owners from build/OWNERS.setnoparent:',
3144 long_text='\n\n'.join(errors)))
3145 return results
3146
3147
jbriance9e12f162016-11-25 07:57:503148def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313149 """Checks that added or removed lines in non third party affected
3150 header files do not lead to new useless class or struct forward
3151 declaration.
jbriance9e12f162016-11-25 07:57:503152 """
3153 results = []
3154 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3155 input_api.re.MULTILINE)
3156 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3157 input_api.re.MULTILINE)
3158 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313159 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193160 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493161 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313162 continue
3163
jbriance9e12f162016-11-25 07:57:503164 if not f.LocalPath().endswith('.h'):
3165 continue
3166
3167 contents = input_api.ReadFile(f)
3168 fwd_decls = input_api.re.findall(class_pattern, contents)
3169 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3170
3171 useless_fwd_decls = []
3172 for decl in fwd_decls:
3173 count = sum(1 for _ in input_api.re.finditer(
3174 r'\b%s\b' % input_api.re.escape(decl), contents))
3175 if count == 1:
3176 useless_fwd_decls.append(decl)
3177
3178 if not useless_fwd_decls:
3179 continue
3180
3181 for line in f.GenerateScmDiff().splitlines():
3182 if (line.startswith('-') and not line.startswith('--') or
3183 line.startswith('+') and not line.startswith('++')):
3184 for decl in useless_fwd_decls:
3185 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3186 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243187 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503188 (f.LocalPath(), decl)))
3189 useless_fwd_decls.remove(decl)
3190
3191 return results
3192
Jinsong Fan91ebbbd2019-04-16 14:57:173193def _CheckAndroidDebuggableBuild(input_api, output_api):
3194 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3195 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3196 this is a debuggable build of Android.
3197 """
3198 build_type_check_pattern = input_api.re.compile(
3199 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3200
3201 errors = []
3202
3203 sources = lambda affected_file: input_api.FilterSourceFile(
3204 affected_file,
3205 black_list=(_EXCLUDED_PATHS +
3206 _TEST_CODE_EXCLUDED_PATHS +
3207 input_api.DEFAULT_BLACK_LIST +
3208 (r"^android_webview[\\/]support_library[\\/]"
3209 "boundary_interfaces[\\/]",
3210 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3211 r'^third_party[\\/].*',
3212 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3213 r"webview[\\/]chromium[\\/]License.*",)),
3214 white_list=[r'.*\.java$'])
3215
3216 for f in input_api.AffectedSourceFiles(sources):
3217 for line_num, line in f.ChangedContents():
3218 if build_type_check_pattern.search(line):
3219 errors.append("%s:%d" % (f.LocalPath(), line_num))
3220
3221 results = []
3222
3223 if errors:
3224 results.append(output_api.PresubmitPromptWarning(
3225 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3226 ' Please use BuildInfo.isDebugAndroid() instead.',
3227 errors))
3228
3229 return results
jbriance9e12f162016-11-25 07:57:503230
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493231# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293232def _CheckAndroidToastUsage(input_api, output_api):
3233 """Checks that code uses org.chromium.ui.widget.Toast instead of
3234 android.widget.Toast (Chromium Toast doesn't force hardware
3235 acceleration on low-end devices, saving memory).
3236 """
3237 toast_import_pattern = input_api.re.compile(
3238 r'^import android\.widget\.Toast;$')
3239
3240 errors = []
3241
3242 sources = lambda affected_file: input_api.FilterSourceFile(
3243 affected_file,
3244 black_list=(_EXCLUDED_PATHS +
3245 _TEST_CODE_EXCLUDED_PATHS +
3246 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043247 (r'^chromecast[\\/].*',
3248 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493249 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293250
3251 for f in input_api.AffectedSourceFiles(sources):
3252 for line_num, line in f.ChangedContents():
3253 if toast_import_pattern.search(line):
3254 errors.append("%s:%d" % (f.LocalPath(), line_num))
3255
3256 results = []
3257
3258 if errors:
3259 results.append(output_api.PresubmitError(
3260 'android.widget.Toast usage is detected. Android toasts use hardware'
3261 ' acceleration, and can be\ncostly on low-end devices. Please use'
3262 ' org.chromium.ui.widget.Toast instead.\n'
3263 'Contact [email protected] if you have any questions.',
3264 errors))
3265
3266 return results
3267
3268
dgnaa68d5e2015-06-10 10:08:223269def _CheckAndroidCrLogUsage(input_api, output_api):
3270 """Checks that new logs using org.chromium.base.Log:
3271 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513272 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223273 """
pkotwicza1dd0b002016-05-16 14:41:043274
torne89540622017-03-24 19:41:303275 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043276 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303277 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043278 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303279 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043280 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3281 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093282 # The customtabs_benchmark is a small app that does not depend on Chromium
3283 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043284 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043285 ]
3286
dgnaa68d5e2015-06-10 10:08:223287 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123288 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3289 class_in_base_pattern = input_api.re.compile(
3290 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3291 has_some_log_import_pattern = input_api.re.compile(
3292 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223293 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
Tomasz Śniatowski3ae2f102020-03-23 15:35:553294 log_call_pattern = input_api.re.compile(r'\bLog\.\w\((?P<tag>\"?\w+)')
dgnaa68d5e2015-06-10 10:08:223295 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463296 r'static final String TAG = "(?P<name>(.*))"')
Tomasz Śniatowski3ae2f102020-03-23 15:35:553297 rough_log_decl_pattern = input_api.re.compile(r'\bString TAG\s*=')
dgnaa68d5e2015-06-10 10:08:223298
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463299 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493300 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043301 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123302
dgnaa68d5e2015-06-10 10:08:223303 tag_decl_errors = []
3304 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123305 tag_errors = []
dgn38736db2015-09-18 19:20:513306 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123307 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223308
3309 for f in input_api.AffectedSourceFiles(sources):
3310 file_content = input_api.ReadFile(f)
3311 has_modified_logs = False
dgnaa68d5e2015-06-10 10:08:223312 # Per line checks
dgn87d9fb62015-06-12 09:15:123313 if (cr_log_import_pattern.search(file_content) or
3314 (class_in_base_pattern.search(file_content) and
3315 not has_some_log_import_pattern.search(file_content))):
3316 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223317 for line_num, line in f.ChangedContents():
Tomasz Śniatowski3ae2f102020-03-23 15:35:553318 if rough_log_decl_pattern.search(line):
3319 has_modified_logs = True
dgnaa68d5e2015-06-10 10:08:223320
3321 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123322 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223323 if match:
3324 has_modified_logs = True
3325
3326 # Make sure it uses "TAG"
3327 if not match.group('tag') == 'TAG':
3328 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123329 else:
3330 # Report non cr Log function calls in changed lines
3331 for line_num, line in f.ChangedContents():
3332 if log_call_pattern.search(line):
3333 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223334
3335 # Per file checks
3336 if has_modified_logs:
3337 # Make sure the tag is using the "cr" prefix and is not too long
3338 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513339 tag_name = match.group('name') if match else None
3340 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223341 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513342 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223343 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513344 elif '.' in tag_name:
3345 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223346
3347 results = []
3348 if tag_decl_errors:
3349 results.append(output_api.PresubmitPromptWarning(
3350 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513351 '"private static final String TAG = "<package tag>".\n'
3352 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223353 tag_decl_errors))
3354
3355 if tag_length_errors:
3356 results.append(output_api.PresubmitError(
3357 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513358 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223359 tag_length_errors))
3360
3361 if tag_errors:
3362 results.append(output_api.PresubmitPromptWarning(
3363 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3364 tag_errors))
3365
dgn87d9fb62015-06-12 09:15:123366 if util_log_errors:
dgn4401aa52015-04-29 16:26:173367 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123368 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3369 util_log_errors))
3370
dgn38736db2015-09-18 19:20:513371 if tag_with_dot_errors:
3372 results.append(output_api.PresubmitPromptWarning(
3373 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3374 tag_with_dot_errors))
3375
dgn4401aa52015-04-29 16:26:173376 return results
3377
3378
Yoland Yanb92fa522017-08-28 17:37:063379def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3380 """Checks that junit.framework.* is no longer used."""
3381 deprecated_junit_framework_pattern = input_api.re.compile(
3382 r'^import junit\.framework\..*;',
3383 input_api.re.MULTILINE)
3384 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493385 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063386 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133387 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063388 for line_num, line in f.ChangedContents():
3389 if deprecated_junit_framework_pattern.search(line):
3390 errors.append("%s:%d" % (f.LocalPath(), line_num))
3391
3392 results = []
3393 if errors:
3394 results.append(output_api.PresubmitError(
3395 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3396 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3397 ' if you have any question.', errors))
3398 return results
3399
3400
3401def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3402 """Checks that if new Java test classes have inheritance.
3403 Either the new test class is JUnit3 test or it is a JUnit4 test class
3404 with a base class, either case is undesirable.
3405 """
3406 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3407
3408 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493409 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063410 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133411 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063412 if not f.OldContents():
3413 class_declaration_start_flag = False
3414 for line_num, line in f.ChangedContents():
3415 if class_declaration_pattern.search(line):
3416 class_declaration_start_flag = True
3417 if class_declaration_start_flag and ' extends ' in line:
3418 errors.append('%s:%d' % (f.LocalPath(), line_num))
3419 if '{' in line:
3420 class_declaration_start_flag = False
3421
3422 results = []
3423 if errors:
3424 results.append(output_api.PresubmitPromptWarning(
3425 'The newly created files include Test classes that inherits from base'
3426 ' class. Please do not use inheritance in JUnit4 tests or add new'
3427 ' JUnit3 tests. Contact [email protected] if you have any'
3428 ' questions.', errors))
3429 return results
3430
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203431
yolandyan45001472016-12-21 21:12:423432def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3433 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3434 deprecated_annotation_import_pattern = input_api.re.compile(
3435 r'^import android\.test\.suitebuilder\.annotation\..*;',
3436 input_api.re.MULTILINE)
3437 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493438 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423439 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133440 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423441 for line_num, line in f.ChangedContents():
3442 if deprecated_annotation_import_pattern.search(line):
3443 errors.append("%s:%d" % (f.LocalPath(), line_num))
3444
3445 results = []
3446 if errors:
3447 results.append(output_api.PresubmitError(
3448 'Annotations in android.test.suitebuilder.annotation have been'
3449 ' deprecated since API level 24. Please use android.support.test.filters'
3450 ' from //third_party/android_support_test_runner:runner_java instead.'
3451 ' Contact [email protected] if you have any questions.', errors))
3452 return results
3453
3454
agrieve7b6479d82015-10-07 14:24:223455def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3456 """Checks if MDPI assets are placed in a correct directory."""
3457 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3458 ('/res/drawable/' in f.LocalPath() or
3459 '/res/drawable-ldrtl/' in f.LocalPath()))
3460 errors = []
3461 for f in input_api.AffectedFiles(include_deletes=False,
3462 file_filter=file_filter):
3463 errors.append(' %s' % f.LocalPath())
3464
3465 results = []
3466 if errors:
3467 results.append(output_api.PresubmitError(
3468 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3469 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3470 '/res/drawable-ldrtl/.\n'
3471 'Contact [email protected] if you have questions.', errors))
3472 return results
3473
3474
Nate Fischer535972b2017-09-16 01:06:183475def _CheckAndroidWebkitImports(input_api, output_api):
3476 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353477 android.webview.ValueCallback except in the WebView glue layer
3478 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183479 """
3480 valuecallback_import_pattern = input_api.re.compile(
3481 r'^import android\.webkit\.ValueCallback;$')
3482
3483 errors = []
3484
3485 sources = lambda affected_file: input_api.FilterSourceFile(
3486 affected_file,
3487 black_list=(_EXCLUDED_PATHS +
3488 _TEST_CODE_EXCLUDED_PATHS +
3489 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353490 (r'^android_webview[\\/]glue[\\/].*',
3491 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493492 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183493
3494 for f in input_api.AffectedSourceFiles(sources):
3495 for line_num, line in f.ChangedContents():
3496 if valuecallback_import_pattern.search(line):
3497 errors.append("%s:%d" % (f.LocalPath(), line_num))
3498
3499 results = []
3500
3501 if errors:
3502 results.append(output_api.PresubmitError(
3503 'android.webkit.ValueCallback usage is detected outside of the glue'
3504 ' layer. To stay compatible with the support library, android.webkit.*'
3505 ' classes should only be used inside the glue layer and'
3506 ' org.chromium.base.Callback should be used instead.',
3507 errors))
3508
3509 return results
3510
3511
Becky Zhou7c69b50992018-12-10 19:37:573512def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3513 """Checks Android XML styles """
3514 import sys
3515 original_sys_path = sys.path
3516 try:
3517 sys.path = sys.path + [input_api.os_path.join(
3518 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3519 import checkxmlstyle
3520 finally:
3521 # Restore sys.path to what it was before.
3522 sys.path = original_sys_path
3523
3524 if is_check_on_upload:
3525 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3526 else:
3527 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3528
3529
agrievef32bcc72016-04-04 14:57:403530class PydepsChecker(object):
3531 def __init__(self, input_api, pydeps_files):
3532 self._file_cache = {}
3533 self._input_api = input_api
3534 self._pydeps_files = pydeps_files
3535
3536 def _LoadFile(self, path):
3537 """Returns the list of paths within a .pydeps file relative to //."""
3538 if path not in self._file_cache:
3539 with open(path) as f:
3540 self._file_cache[path] = f.read()
3541 return self._file_cache[path]
3542
3543 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3544 """Returns an interable of paths within the .pydep, relativized to //."""
3545 os_path = self._input_api.os_path
3546 pydeps_dir = os_path.dirname(pydeps_path)
3547 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3548 if not l.startswith('*'))
3549 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3550
3551 def _CreateFilesToPydepsMap(self):
3552 """Returns a map of local_path -> list_of_pydeps."""
3553 ret = {}
3554 for pydep_local_path in self._pydeps_files:
3555 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3556 ret.setdefault(path, []).append(pydep_local_path)
3557 return ret
3558
3559 def ComputeAffectedPydeps(self):
3560 """Returns an iterable of .pydeps files that might need regenerating."""
3561 affected_pydeps = set()
3562 file_to_pydeps_map = None
3563 for f in self._input_api.AffectedFiles(include_deletes=True):
3564 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463565 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3566 # subrepositories. We can't figure out which files change, so re-check
3567 # all files.
3568 # Changes to print_python_deps.py affect all .pydeps.
3569 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403570 return self._pydeps_files
3571 elif local_path.endswith('.pydeps'):
3572 if local_path in self._pydeps_files:
3573 affected_pydeps.add(local_path)
3574 elif local_path.endswith('.py'):
3575 if file_to_pydeps_map is None:
3576 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3577 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3578 return affected_pydeps
3579
3580 def DetermineIfStale(self, pydeps_path):
3581 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413582 import difflib
John Budorick47ca3fe2018-02-10 00:53:103583 import os
3584
agrievef32bcc72016-04-04 14:57:403585 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3586 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103587 env = dict(os.environ)
3588 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403589 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103590 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413591 old_contents = old_pydeps_data[2:]
3592 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403593 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413594 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403595
3596
Tibor Goldschwendt360793f72019-06-25 18:23:493597def _ParseGclientArgs():
3598 args = {}
3599 with open('build/config/gclient_args.gni', 'r') as f:
3600 for line in f:
3601 line = line.strip()
3602 if not line or line.startswith('#'):
3603 continue
3604 attribute, value = line.split('=')
3605 args[attribute.strip()] = value.strip()
3606 return args
3607
3608
agrievef32bcc72016-04-04 14:57:403609def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3610 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403611 # This check is for Python dependency lists (.pydeps files), and involves
3612 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3613 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283614 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003615 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493616 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403617 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3618 results = []
3619 # First, check for new / deleted .pydeps.
3620 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033621 # Check whether we are running the presubmit check for a file in src.
3622 # f.LocalPath is relative to repo (src, or internal repo).
3623 # os_path.exists is relative to src repo.
3624 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3625 # to src and we can conclude that the pydeps is in src.
3626 if input_api.os_path.exists(f.LocalPath()):
3627 if f.LocalPath().endswith('.pydeps'):
3628 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3629 results.append(output_api.PresubmitError(
3630 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3631 'remove %s' % f.LocalPath()))
3632 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3633 results.append(output_api.PresubmitError(
3634 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3635 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403636
3637 if results:
3638 return results
3639
3640 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3641
3642 for pydep_path in checker.ComputeAffectedPydeps():
3643 try:
phajdan.jr0d9878552016-11-04 10:49:413644 result = checker.DetermineIfStale(pydep_path)
3645 if result:
3646 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403647 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413648 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3649 'To regenerate, run:\n\n %s' %
3650 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403651 except input_api.subprocess.CalledProcessError as error:
3652 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3653 long_text=error.output)]
3654
3655 return results
3656
3657
glidere61efad2015-02-18 17:39:433658def _CheckSingletonInHeaders(input_api, output_api):
3659 """Checks to make sure no header files have |Singleton<|."""
3660 def FileFilter(affected_file):
3661 # It's ok for base/memory/singleton.h to have |Singleton<|.
3662 black_list = (_EXCLUDED_PATHS +
3663 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043664 (r"^base[\\/]memory[\\/]singleton\.h$",
3665 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473666 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433667 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3668
sergeyu34d21222015-09-16 00:11:443669 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433670 files = []
3671 for f in input_api.AffectedSourceFiles(FileFilter):
3672 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3673 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3674 contents = input_api.ReadFile(f)
3675 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243676 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433677 pattern.search(line)):
3678 files.append(f)
3679 break
3680
3681 if files:
yolandyandaabc6d2016-04-18 18:29:393682 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443683 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433684 'Please move them to an appropriate source file so that the ' +
3685 'template gets instantiated in a single compilation unit.',
3686 files) ]
3687 return []
3688
3689
[email protected]fd20b902014-05-09 02:14:533690_DEPRECATED_CSS = [
3691 # Values
3692 ( "-webkit-box", "flex" ),
3693 ( "-webkit-inline-box", "inline-flex" ),
3694 ( "-webkit-flex", "flex" ),
3695 ( "-webkit-inline-flex", "inline-flex" ),
3696 ( "-webkit-min-content", "min-content" ),
3697 ( "-webkit-max-content", "max-content" ),
3698
3699 # Properties
3700 ( "-webkit-background-clip", "background-clip" ),
3701 ( "-webkit-background-origin", "background-origin" ),
3702 ( "-webkit-background-size", "background-size" ),
3703 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443704 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533705
3706 # Functions
3707 ( "-webkit-gradient", "gradient" ),
3708 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3709 ( "-webkit-linear-gradient", "linear-gradient" ),
3710 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3711 ( "-webkit-radial-gradient", "radial-gradient" ),
3712 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3713]
3714
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203715
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493716# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243717def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533718 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253719 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343720 documentation and iOS CSS for dom distiller
3721 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253722 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533723 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493724 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253725 black_list = (_EXCLUDED_PATHS +
3726 _TEST_CODE_EXCLUDED_PATHS +
3727 input_api.DEFAULT_BLACK_LIST +
3728 (r"^chrome/common/extensions/docs",
3729 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343730 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443731 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253732 r"^native_client_sdk"))
3733 file_filter = lambda f: input_api.FilterSourceFile(
3734 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533735 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3736 for line_num, line in fpath.ChangedContents():
3737 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023738 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533739 results.append(output_api.PresubmitError(
3740 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3741 (fpath.LocalPath(), line_num, deprecated_value, value)))
3742 return results
3743
mohan.reddyf21db962014-10-16 12:26:473744
rlanday6802cf632017-05-30 17:48:363745def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363746 bad_files = {}
3747 for f in input_api.AffectedFiles(include_deletes=False):
3748 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493749 not f.LocalPath().startswith('third_party/blink') and
3750 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363751 continue
3752
Daniel Bratell65b033262019-04-23 08:17:063753 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363754 continue
3755
Vaclav Brozekd5de76a2018-03-17 07:57:503756 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363757 if "#include" in line and "../" in line]
3758 if not relative_includes:
3759 continue
3760 bad_files[f.LocalPath()] = relative_includes
3761
3762 if not bad_files:
3763 return []
3764
3765 error_descriptions = []
3766 for file_path, bad_lines in bad_files.iteritems():
3767 error_description = file_path
3768 for line in bad_lines:
3769 error_description += '\n ' + line
3770 error_descriptions.append(error_description)
3771
3772 results = []
3773 results.append(output_api.PresubmitError(
3774 'You added one or more relative #include paths (including "../").\n'
3775 'These shouldn\'t be used because they can be used to include headers\n'
3776 'from code that\'s not correctly specified as a dependency in the\n'
3777 'relevant BUILD.gn file(s).',
3778 error_descriptions))
3779
3780 return results
3781
Takeshi Yoshinoe387aa32017-08-02 13:16:133782
Daniel Bratell65b033262019-04-23 08:17:063783def _CheckForCcIncludes(input_api, output_api):
3784 """Check that nobody tries to include a cc file. It's a relatively
3785 common error which results in duplicate symbols in object
3786 files. This may not always break the build until someone later gets
3787 very confusing linking errors."""
3788 results = []
3789 for f in input_api.AffectedFiles(include_deletes=False):
3790 # We let third_party code do whatever it wants
3791 if (f.LocalPath().startswith('third_party') and
3792 not f.LocalPath().startswith('third_party/blink') and
3793 not f.LocalPath().startswith('third_party\\blink')):
3794 continue
3795
3796 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3797 continue
3798
3799 for _, line in f.ChangedContents():
3800 if line.startswith('#include "'):
3801 included_file = line.split('"')[1]
3802 if _IsCPlusPlusFile(input_api, included_file):
3803 # The most common naming for external files with C++ code,
3804 # apart from standard headers, is to call them foo.inc, but
3805 # Chromium sometimes uses foo-inc.cc so allow that as well.
3806 if not included_file.endswith(('.h', '-inc.cc')):
3807 results.append(output_api.PresubmitError(
3808 'Only header files or .inc files should be included in other\n'
3809 'C++ files. Compiling the contents of a cc file more than once\n'
3810 'will cause duplicate information in the build which may later\n'
3811 'result in strange link_errors.\n' +
3812 f.LocalPath() + ':\n ' +
3813 line))
3814
3815 return results
3816
3817
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203818def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3819 if not isinstance(key, ast.Str):
3820 return 'Key at line %d must be a string literal' % key.lineno
3821 if not isinstance(value, ast.Dict):
3822 return 'Value at line %d must be a dict' % value.lineno
3823 if len(value.keys) != 1:
3824 return 'Dict at line %d must have single entry' % value.lineno
3825 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3826 return (
3827 'Entry at line %d must have a string literal \'filepath\' as key' %
3828 value.lineno)
3829 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133830
Takeshi Yoshinoe387aa32017-08-02 13:16:133831
Sergey Ulanov4af16052018-11-08 02:41:463832def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203833 if not isinstance(key, ast.Str):
3834 return 'Key at line %d must be a string literal' % key.lineno
3835 if not isinstance(value, ast.List):
3836 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463837 for element in value.elts:
3838 if not isinstance(element, ast.Str):
3839 return 'Watchlist elements on line %d is not a string' % key.lineno
3840 if not email_regex.match(element.s):
3841 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3842 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203843 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133844
Takeshi Yoshinoe387aa32017-08-02 13:16:133845
Sergey Ulanov4af16052018-11-08 02:41:463846def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203847 mismatch_template = (
3848 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3849 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133850
Sergey Ulanov4af16052018-11-08 02:41:463851 email_regex = input_api.re.compile(
3852 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3853
3854 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203855 i = 0
3856 last_key = ''
3857 while True:
3858 if i >= len(wd_dict.keys):
3859 if i >= len(w_dict.keys):
3860 return None
3861 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3862 elif i >= len(w_dict.keys):
3863 return (
3864 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133865
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203866 wd_key = wd_dict.keys[i]
3867 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133868
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203869 result = _CheckWatchlistDefinitionsEntrySyntax(
3870 wd_key, wd_dict.values[i], ast)
3871 if result is not None:
3872 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133873
Sergey Ulanov4af16052018-11-08 02:41:463874 result = _CheckWatchlistsEntrySyntax(
3875 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203876 if result is not None:
3877 return 'Bad entry in WATCHLISTS dict: %s' % result
3878
3879 if wd_key.s != w_key.s:
3880 return mismatch_template % (
3881 '%s at line %d' % (wd_key.s, wd_key.lineno),
3882 '%s at line %d' % (w_key.s, w_key.lineno))
3883
3884 if wd_key.s < last_key:
3885 return (
3886 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3887 (wd_key.lineno, w_key.lineno))
3888 last_key = wd_key.s
3889
3890 i = i + 1
3891
3892
Sergey Ulanov4af16052018-11-08 02:41:463893def _CheckWATCHLISTSSyntax(expression, input_api):
3894 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203895 if not isinstance(expression, ast.Expression):
3896 return 'WATCHLISTS file must contain a valid expression'
3897 dictionary = expression.body
3898 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3899 return 'WATCHLISTS file must have single dict with exactly two entries'
3900
3901 first_key = dictionary.keys[0]
3902 first_value = dictionary.values[0]
3903 second_key = dictionary.keys[1]
3904 second_value = dictionary.values[1]
3905
3906 if (not isinstance(first_key, ast.Str) or
3907 first_key.s != 'WATCHLIST_DEFINITIONS' or
3908 not isinstance(first_value, ast.Dict)):
3909 return (
3910 'The first entry of the dict in WATCHLISTS file must be '
3911 'WATCHLIST_DEFINITIONS dict')
3912
3913 if (not isinstance(second_key, ast.Str) or
3914 second_key.s != 'WATCHLISTS' or
3915 not isinstance(second_value, ast.Dict)):
3916 return (
3917 'The second entry of the dict in WATCHLISTS file must be '
3918 'WATCHLISTS dict')
3919
Sergey Ulanov4af16052018-11-08 02:41:463920 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133921
3922
3923def _CheckWATCHLISTS(input_api, output_api):
3924 for f in input_api.AffectedFiles(include_deletes=False):
3925 if f.LocalPath() == 'WATCHLISTS':
3926 contents = input_api.ReadFile(f, 'r')
3927
3928 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203929 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133930 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203931 # Get an AST tree for it and scan the tree for detailed style checking.
3932 expression = input_api.ast.parse(
3933 contents, filename='WATCHLISTS', mode='eval')
3934 except ValueError as e:
3935 return [output_api.PresubmitError(
3936 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3937 except SyntaxError as e:
3938 return [output_api.PresubmitError(
3939 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3940 except TypeError as e:
3941 return [output_api.PresubmitError(
3942 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133943
Sergey Ulanov4af16052018-11-08 02:41:463944 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203945 if result is not None:
3946 return [output_api.PresubmitError(result)]
3947 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133948
3949 return []
3950
3951
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193952def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3953 """Checks that newly added header files have corresponding GN changes.
3954 Note that this is only a heuristic. To be precise, run script:
3955 build/check_gn_headers.py.
3956 """
3957
3958 def headers(f):
3959 return input_api.FilterSourceFile(
3960 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3961
3962 new_headers = []
3963 for f in input_api.AffectedSourceFiles(headers):
3964 if f.Action() != 'A':
3965 continue
3966 new_headers.append(f.LocalPath())
3967
3968 def gn_files(f):
3969 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3970
3971 all_gn_changed_contents = ''
3972 for f in input_api.AffectedSourceFiles(gn_files):
3973 for _, line in f.ChangedContents():
3974 all_gn_changed_contents += line
3975
3976 problems = []
3977 for header in new_headers:
3978 basename = input_api.os_path.basename(header)
3979 if basename not in all_gn_changed_contents:
3980 problems.append(header)
3981
3982 if problems:
3983 return [output_api.PresubmitPromptWarning(
3984 'Missing GN changes for new header files', items=sorted(problems),
3985 long_text='Please double check whether newly added header files need '
3986 'corresponding changes in gn or gni files.\nThis checking is only a '
3987 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3988 'Read https://crbug.com/661774 for more info.')]
3989 return []
3990
3991
Michael Giuffridad3bc8672018-10-25 22:48:023992def _CheckCorrectProductNameInMessages(input_api, output_api):
3993 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3994
3995 This assumes we won't intentionally reference one product from the other
3996 product.
3997 """
3998 all_problems = []
3999 test_cases = [{
4000 "filename_postfix": "google_chrome_strings.grd",
4001 "correct_name": "Chrome",
4002 "incorrect_name": "Chromium",
4003 }, {
4004 "filename_postfix": "chromium_strings.grd",
4005 "correct_name": "Chromium",
4006 "incorrect_name": "Chrome",
4007 }]
4008
4009 for test_case in test_cases:
4010 problems = []
4011 filename_filter = lambda x: x.LocalPath().endswith(
4012 test_case["filename_postfix"])
4013
4014 # Check each new line. Can yield false positives in multiline comments, but
4015 # easier than trying to parse the XML because messages can have nested
4016 # children, and associating message elements with affected lines is hard.
4017 for f in input_api.AffectedSourceFiles(filename_filter):
4018 for line_num, line in f.ChangedContents():
4019 if "<message" in line or "<!--" in line or "-->" in line:
4020 continue
4021 if test_case["incorrect_name"] in line:
4022 problems.append(
4023 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
4024
4025 if problems:
4026 message = (
4027 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
4028 % (test_case["correct_name"], test_case["correct_name"],
4029 test_case["incorrect_name"]))
4030 all_problems.append(
4031 output_api.PresubmitPromptWarning(message, items=problems))
4032
4033 return all_problems
4034
4035
Dirk Pranke3c18a382019-03-15 01:07:514036def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4037 # TODO(crbug.com/941824): We need to make sure the entries in
4038 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4039 # so that users of //buildtools in other projects get the same tooling
4040 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4041 # support to gclient, we can eliminate the duplication and delete
4042 # this presubmit check.
4043
4044 # Update this regexp if new revisions are added to the files.
4045 rev_regexp = input_api.re.compile(
Xiaohui Chen3fdc6742020-02-29 02:13:264046 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:514047
4048 # If a user is changing one revision, they need to change the same
4049 # line in both files. This means that any given change should contain
4050 # exactly the same list of changed lines that match the regexps. The
4051 # replace(' ', '') call allows us to ignore whitespace changes to the
4052 # lines. The 'long_text' parameter to the error will contain the
4053 # list of changed lines in both files, which should make it easy enough
4054 # to spot the error without going overboard in this implementation.
4055 revs_changes = {
4056 'DEPS': {},
4057 'buildtools/DEPS': {},
4058 }
4059 long_text = ''
4060
4061 for f in input_api.AffectedFiles(
4062 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4063 for line_num, line in f.ChangedContents():
4064 if rev_regexp.search(line):
4065 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4066 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4067
4068 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4069 return [output_api.PresubmitError(
4070 'Change buildtools revisions in sync in both //DEPS and '
4071 '//buildtools/DEPS.', long_text=long_text + '\n')]
4072 else:
4073 return []
4074
4075
Daniel Bratell93eb6c62019-04-29 20:13:364076def _CheckForTooLargeFiles(input_api, output_api):
4077 """Avoid large files, especially binary files, in the repository since
4078 git doesn't scale well for those. They will be in everyone's repo
4079 clones forever, forever making Chromium slower to clone and work
4080 with."""
4081
4082 # Uploading files to cloud storage is not trivial so we don't want
4083 # to set the limit too low, but the upper limit for "normal" large
4084 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4085 # anything over 20 MB is exceptional.
4086 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4087
4088 too_large_files = []
4089 for f in input_api.AffectedFiles():
4090 # Check both added and modified files (but not deleted files).
4091 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384092 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364093 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4094 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4095
4096 if too_large_files:
4097 message = (
4098 'Do not commit large files to git since git scales badly for those.\n' +
4099 'Instead put the large files in cloud storage and use DEPS to\n' +
4100 'fetch them.\n' + '\n'.join(too_large_files)
4101 )
4102 return [output_api.PresubmitError(
4103 'Too large files found in commit', long_text=message + '\n')]
4104 else:
4105 return []
4106
Max Morozb47503b2019-08-08 21:03:274107
4108def _CheckFuzzTargets(input_api, output_api):
4109 """Checks specific for fuzz target sources."""
4110 EXPORTED_SYMBOLS = [
4111 'LLVMFuzzerInitialize',
4112 'LLVMFuzzerCustomMutator',
4113 'LLVMFuzzerCustomCrossOver',
4114 'LLVMFuzzerMutate',
4115 ]
4116
4117 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4118
4119 def FilterFile(affected_file):
4120 """Ignore libFuzzer source code."""
4121 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4122 black_list = r"^third_party[\\/]libFuzzer"
4123
4124 return input_api.FilterSourceFile(
4125 affected_file,
4126 white_list=[white_list],
4127 black_list=[black_list])
4128
4129 files_with_missing_header = []
4130 for f in input_api.AffectedSourceFiles(FilterFile):
4131 contents = input_api.ReadFile(f, 'r')
4132 if REQUIRED_HEADER in contents:
4133 continue
4134
4135 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4136 files_with_missing_header.append(f.LocalPath())
4137
4138 if not files_with_missing_header:
4139 return []
4140
4141 long_text = (
4142 'If you define any of the libFuzzer optional functions (%s), it is '
4143 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4144 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4145 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4146 'to access command line arguments passed to the fuzzer. Instead, prefer '
4147 'static initialization and shared resources as documented in '
4148 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4149 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4150 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4151 )
4152
4153 return [output_api.PresubmitPromptWarning(
4154 message="Missing '%s' in:" % REQUIRED_HEADER,
4155 items=files_with_missing_header,
4156 long_text=long_text)]
4157
4158
Mohamed Heikald048240a2019-11-12 16:57:374159def _CheckNewImagesWarning(input_api, output_api):
4160 """
4161 Warns authors who add images into the repo to make sure their images are
4162 optimized before committing.
4163 """
4164 images_added = False
4165 image_paths = []
4166 errors = []
4167 filter_lambda = lambda x: input_api.FilterSourceFile(
4168 x,
4169 black_list=(('(?i).*test', r'.*\/junit\/')
4170 + input_api.DEFAULT_BLACK_LIST),
4171 white_list=[r'.*\/(drawable|mipmap)' ]
4172 )
4173 for f in input_api.AffectedFiles(
4174 include_deletes=False, file_filter=filter_lambda):
4175 local_path = f.LocalPath().lower()
4176 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4177 images_added = True
4178 image_paths.append(f)
4179 if images_added:
4180 errors.append(output_api.PresubmitPromptWarning(
4181 'It looks like you are trying to commit some images. If these are '
4182 'non-test-only images, please make sure to read and apply the tips in '
4183 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4184 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4185 'FYI only and will not block your CL on the CQ.', image_paths))
4186 return errors
4187
4188
dgnaa68d5e2015-06-10 10:08:224189def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574190 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224191 results = []
dgnaa68d5e2015-06-10 10:08:224192 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174193 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224194 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294195 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064196 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4197 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424198 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184199 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574200 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374201 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154202 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574203 return results
4204
4205def _AndroidSpecificOnCommitChecks(input_api, output_api):
4206 """Groups commit checks that target android code."""
4207 results = []
4208 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224209 return results
4210
Chris Hall59f8d0c72020-05-01 07:31:194211# TODO(chrishall): could we additionally match on any path owned by
4212# ui/accessibility/OWNERS ?
4213_ACCESSIBILITY_PATHS = (
4214 r"^chrome[\\/]browser.*[\\/]accessibility[\\/]",
4215 r"^chrome[\\/]browser[\\/]extensions[\\/]api[\\/]automation.*[\\/]",
4216 r"^chrome[\\/]renderer[\\/]extensions[\\/]accessibility_.*",
4217 r"^chrome[\\/]tests[\\/]data[\\/]accessibility[\\/]",
4218 r"^content[\\/]browser[\\/]accessibility[\\/]",
4219 r"^content[\\/]renderer[\\/]accessibility[\\/]",
4220 r"^content[\\/]tests[\\/]data[\\/]accessibility[\\/]",
4221 r"^extensions[\\/]renderer[\\/]api[\\/]automation[\\/]",
4222 r"^ui[\\/]accessibility[\\/]",
4223 r"^ui[\\/]views[\\/]accessibility[\\/]",
4224)
4225
4226def _CheckAccessibilityRelnotesField(input_api, output_api):
4227 """Checks that commits to accessibility code contain an AX-Relnotes field in
4228 their commit message."""
4229 def FileFilter(affected_file):
4230 paths = _ACCESSIBILITY_PATHS
4231 return input_api.FilterSourceFile(affected_file, white_list=paths)
4232
4233 # Only consider changes affecting accessibility paths.
4234 if not any(input_api.AffectedFiles(file_filter=FileFilter)):
4235 return []
4236
4237 relnotes = input_api.change.GitFootersFromDescription().get('AX-Relnotes', [])
4238 if relnotes:
4239 return []
4240
4241 # TODO(chrishall): link to Relnotes documentation in message.
4242 message = ("Missing 'AX-Relnotes:' field required for accessibility changes"
4243 "\n please add 'AX-Relnotes: [release notes].' to describe any "
4244 "user-facing changes"
4245 "\n otherwise add 'AX-Relnotes: n/a.' if this change has no "
4246 "user-facing effects"
4247 "\n if this is confusing or annoying then please contact members "
4248 "of ui/accessibility/OWNERS.")
4249
4250 return [output_api.PresubmitNotifyResult(message)]
dgnaa68d5e2015-06-10 10:08:224251
[email protected]22c9bd72011-03-27 16:47:394252def _CommonChecks(input_api, output_api):
4253 """Checks common to both upload and commit."""
4254 results = []
4255 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384256 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544257 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084258
4259 author = input_api.change.author_email
4260 if author and author not in _KNOWN_ROBOTS:
4261 results.extend(
4262 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4263
Chris Hall59f8d0c72020-05-01 07:31:194264 results.extend(_CheckAccessibilityRelnotesField(input_api, output_api))
[email protected]55459852011-08-10 15:17:194265 results.extend(
[email protected]760deea2013-12-10 19:33:494266 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234267 results.extend(
4268 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544269 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184270 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344271 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524272 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224273 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444274 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594275 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314276 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064277 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124278 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184279 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224280 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304281 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494282 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034283 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494284 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444285 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294286 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274287 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074288 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544289 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444290 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394291 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554292 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044293 results.extend(
4294 input_api.canned_checks.CheckChangeHasNoTabs(
4295 input_api,
4296 output_api,
4297 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404298 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164299 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084300 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244301 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474302 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044303 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054304 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144305 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234306 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434307 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404308 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154309 results.extend(_CheckJavaStyle(input_api, output_api))
Wez17c66962020-04-29 15:26:034310 results.extend(_CheckSecurityOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264311 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504312 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364313 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064314 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134315 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434316 results.extend(input_api.RunTests(
4317 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144318 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Mustafa Emre Acer51f2f742020-03-09 19:41:124319 results.extend(_CheckTranslationExpectations(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024320 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514321 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364322 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004323 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244324
Vaclav Brozekcdc7defb2018-03-20 09:54:354325 for f in input_api.AffectedFiles():
4326 path, name = input_api.os_path.split(f.LocalPath())
4327 if name == 'PRESUBMIT.py':
4328 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004329 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4330 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074331 # The PRESUBMIT.py file (and the directory containing it) might
4332 # have been affected by being moved or removed, so only try to
4333 # run the tests if they still exist.
4334 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4335 input_api, output_api, full_path,
4336 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394337 return results
[email protected]1f7b4172010-01-28 01:17:344338
[email protected]b337cb5b2011-01-23 21:24:054339
[email protected]b8079ae4a2012-12-05 19:56:494340def _CheckPatchFiles(input_api, output_api):
4341 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4342 if f.LocalPath().endswith(('.orig', '.rej'))]
4343 if problems:
4344 return [output_api.PresubmitError(
4345 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034346 else:
4347 return []
[email protected]b8079ae4a2012-12-05 19:56:494348
4349
Kent Tamura5a8755d2017-06-29 23:37:074350def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214351 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4352 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4353 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074354 include_re = input_api.re.compile(
4355 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4356 extension_re = input_api.re.compile(r'\.[a-z]+$')
4357 errors = []
4358 for f in input_api.AffectedFiles():
4359 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4360 continue
4361 found_line_number = None
4362 found_macro = None
4363 for line_num, line in f.ChangedContents():
4364 match = macro_re.search(line)
4365 if match:
4366 found_line_number = line_num
4367 found_macro = match.group(2)
4368 break
4369 if not found_line_number:
4370 continue
4371
4372 found_include = False
4373 for line in f.NewContents():
4374 if include_re.search(line):
4375 found_include = True
4376 break
4377 if found_include:
4378 continue
4379
4380 if not f.LocalPath().endswith('.h'):
4381 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4382 try:
4383 content = input_api.ReadFile(primary_header_path, 'r')
4384 if include_re.search(content):
4385 continue
4386 except IOError:
4387 pass
4388 errors.append('%s:%d %s macro is used without including build/'
4389 'build_config.h.'
4390 % (f.LocalPath(), found_line_number, found_macro))
4391 if errors:
4392 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4393 return []
4394
4395
[email protected]b00342e7f2013-03-26 16:21:544396def _DidYouMeanOSMacro(bad_macro):
4397 try:
4398 return {'A': 'OS_ANDROID',
4399 'B': 'OS_BSD',
4400 'C': 'OS_CHROMEOS',
4401 'F': 'OS_FREEBSD',
4402 'L': 'OS_LINUX',
4403 'M': 'OS_MACOSX',
4404 'N': 'OS_NACL',
4405 'O': 'OS_OPENBSD',
4406 'P': 'OS_POSIX',
4407 'S': 'OS_SOLARIS',
4408 'W': 'OS_WIN'}[bad_macro[3].upper()]
4409 except KeyError:
4410 return ''
4411
4412
4413def _CheckForInvalidOSMacrosInFile(input_api, f):
4414 """Check for sensible looking, totally invalid OS macros."""
4415 preprocessor_statement = input_api.re.compile(r'^\s*#')
4416 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4417 results = []
4418 for lnum, line in f.ChangedContents():
4419 if preprocessor_statement.search(line):
4420 for match in os_macro.finditer(line):
4421 if not match.group(1) in _VALID_OS_MACROS:
4422 good = _DidYouMeanOSMacro(match.group(1))
4423 did_you_mean = ' (did you mean %s?)' % good if good else ''
4424 results.append(' %s:%d %s%s' % (f.LocalPath(),
4425 lnum,
4426 match.group(1),
4427 did_you_mean))
4428 return results
4429
4430
4431def _CheckForInvalidOSMacros(input_api, output_api):
4432 """Check all affected files for invalid OS macros."""
4433 bad_macros = []
tzik3f295992018-12-04 20:32:234434 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474435 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544436 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4437
4438 if not bad_macros:
4439 return []
4440
4441 return [output_api.PresubmitError(
4442 'Possibly invalid OS macro[s] found. Please fix your code\n'
4443 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4444
lliabraa35bab3932014-10-01 12:16:444445
4446def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4447 """Check all affected files for invalid "if defined" macros."""
4448 ALWAYS_DEFINED_MACROS = (
4449 "TARGET_CPU_PPC",
4450 "TARGET_CPU_PPC64",
4451 "TARGET_CPU_68K",
4452 "TARGET_CPU_X86",
4453 "TARGET_CPU_ARM",
4454 "TARGET_CPU_MIPS",
4455 "TARGET_CPU_SPARC",
4456 "TARGET_CPU_ALPHA",
4457 "TARGET_IPHONE_SIMULATOR",
4458 "TARGET_OS_EMBEDDED",
4459 "TARGET_OS_IPHONE",
4460 "TARGET_OS_MAC",
4461 "TARGET_OS_UNIX",
4462 "TARGET_OS_WIN32",
4463 )
4464 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4465 results = []
4466 for lnum, line in f.ChangedContents():
4467 for match in ifdef_macro.finditer(line):
4468 if match.group(1) in ALWAYS_DEFINED_MACROS:
4469 always_defined = ' %s is always defined. ' % match.group(1)
4470 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4471 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4472 lnum,
4473 always_defined,
4474 did_you_mean))
4475 return results
4476
4477
4478def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4479 """Check all affected files for invalid "if defined" macros."""
4480 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054481 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444482 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054483 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214484 continue
lliabraa35bab3932014-10-01 12:16:444485 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4486 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4487
4488 if not bad_macros:
4489 return []
4490
4491 return [output_api.PresubmitError(
4492 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4493 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4494 bad_macros)]
4495
4496
mlamouria82272622014-09-16 18:45:044497def _CheckForIPCRules(input_api, output_api):
4498 """Check for same IPC rules described in
4499 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4500 """
4501 base_pattern = r'IPC_ENUM_TRAITS\('
4502 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4503 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4504
4505 problems = []
4506 for f in input_api.AffectedSourceFiles(None):
4507 local_path = f.LocalPath()
4508 if not local_path.endswith('.h'):
4509 continue
4510 for line_number, line in f.ChangedContents():
4511 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4512 problems.append(
4513 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4514
4515 if problems:
4516 return [output_api.PresubmitPromptWarning(
4517 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4518 else:
4519 return []
4520
[email protected]b00342e7f2013-03-26 16:21:544521
Stephen Martinis97a394142018-06-07 23:06:054522def _CheckForLongPathnames(input_api, output_api):
4523 """Check to make sure no files being submitted have long paths.
4524 This causes issues on Windows.
4525 """
4526 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194527 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054528 local_path = f.LocalPath()
4529 # Windows has a path limit of 260 characters. Limit path length to 200 so
4530 # that we have some extra for the prefix on dev machines and the bots.
4531 if len(local_path) > 200:
4532 problems.append(local_path)
4533
4534 if problems:
4535 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4536 else:
4537 return []
4538
4539
Daniel Bratell8ba52722018-03-02 16:06:144540def _CheckForIncludeGuards(input_api, output_api):
4541 """Check that header files have proper guards against multiple inclusion.
4542 If a file should not have such guards (and it probably should) then it
4543 should include the string "no-include-guard-because-multiply-included".
4544 """
Daniel Bratell6a75baef62018-06-04 10:04:454545 def is_chromium_header_file(f):
4546 # We only check header files under the control of the Chromium
4547 # project. That is, those outside third_party apart from
4548 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324549 # We also exclude *_message_generator.h headers as they use
4550 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454551 file_with_path = input_api.os_path.normpath(f.LocalPath())
4552 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324553 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454554 (not file_with_path.startswith('third_party') or
4555 file_with_path.startswith(
4556 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144557
4558 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344559 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144560
4561 errors = []
4562
Daniel Bratell6a75baef62018-06-04 10:04:454563 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144564 guard_name = None
4565 guard_line_number = None
4566 seen_guard_end = False
4567
4568 file_with_path = input_api.os_path.normpath(f.LocalPath())
4569 base_file_name = input_api.os_path.splitext(
4570 input_api.os_path.basename(file_with_path))[0]
4571 upper_base_file_name = base_file_name.upper()
4572
4573 expected_guard = replace_special_with_underscore(
4574 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144575
4576 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574577 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4578 # are too many (1000+) files with slight deviations from the
4579 # coding style. The most important part is that the include guard
4580 # is there, and that it's unique, not the name so this check is
4581 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144582 #
4583 # As code becomes more uniform, this could be made stricter.
4584
4585 guard_name_pattern_list = [
4586 # Anything with the right suffix (maybe with an extra _).
4587 r'\w+_H__?',
4588
Daniel Bratell39b5b062018-05-16 18:09:574589 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144590 r'\w+_h',
4591
4592 # Anything including the uppercase name of the file.
4593 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4594 upper_base_file_name)) + r'\w*',
4595 ]
4596 guard_name_pattern = '|'.join(guard_name_pattern_list)
4597 guard_pattern = input_api.re.compile(
4598 r'#ifndef\s+(' + guard_name_pattern + ')')
4599
4600 for line_number, line in enumerate(f.NewContents()):
4601 if 'no-include-guard-because-multiply-included' in line:
4602 guard_name = 'DUMMY' # To not trigger check outside the loop.
4603 break
4604
4605 if guard_name is None:
4606 match = guard_pattern.match(line)
4607 if match:
4608 guard_name = match.group(1)
4609 guard_line_number = line_number
4610
Daniel Bratell39b5b062018-05-16 18:09:574611 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454612 # don't match the chromium style guide, but new files should
4613 # get it right.
4614 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574615 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144616 errors.append(output_api.PresubmitPromptWarning(
4617 'Header using the wrong include guard name %s' % guard_name,
4618 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574619 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144620 else:
4621 # The line after #ifndef should have a #define of the same name.
4622 if line_number == guard_line_number + 1:
4623 expected_line = '#define %s' % guard_name
4624 if line != expected_line:
4625 errors.append(output_api.PresubmitPromptWarning(
4626 'Missing "%s" for include guard' % expected_line,
4627 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4628 'Expected: %r\nGot: %r' % (expected_line, line)))
4629
4630 if not seen_guard_end and line == '#endif // %s' % guard_name:
4631 seen_guard_end = True
4632 elif seen_guard_end:
4633 if line.strip() != '':
4634 errors.append(output_api.PresubmitPromptWarning(
4635 'Include guard %s not covering the whole file' % (
4636 guard_name), [f.LocalPath()]))
4637 break # Nothing else to check and enough to warn once.
4638
4639 if guard_name is None:
4640 errors.append(output_api.PresubmitPromptWarning(
4641 'Missing include guard %s' % expected_guard,
4642 [f.LocalPath()],
4643 'Missing include guard in %s\n'
4644 'Recommended name: %s\n'
4645 'This check can be disabled by having the string\n'
4646 'no-include-guard-because-multiply-included in the header.' %
4647 (f.LocalPath(), expected_guard)))
4648
4649 return errors
4650
4651
mostynbb639aca52015-01-07 20:31:234652def _CheckForWindowsLineEndings(input_api, output_api):
4653 """Check source code and known ascii text files for Windows style line
4654 endings.
4655 """
earthdok1b5e0ee2015-03-10 15:19:104656 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234657
4658 file_inclusion_pattern = (
4659 known_text_files,
4660 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4661 )
4662
mostynbb639aca52015-01-07 20:31:234663 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534664 source_file_filter = lambda f: input_api.FilterSourceFile(
4665 f, white_list=file_inclusion_pattern, black_list=None)
4666 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504667 include_file = False
4668 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234669 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504670 include_file = True
4671 if include_file:
4672 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234673
4674 if problems:
4675 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4676 'these files to contain Windows style line endings?\n' +
4677 '\n'.join(problems))]
4678
4679 return []
4680
4681
Vaclav Brozekd5de76a2018-03-17 07:57:504682def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134683 """Checks that all source files use SYSLOG properly."""
4684 syslog_files = []
4685 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564686 for line_number, line in f.ChangedContents():
4687 if 'SYSLOG' in line:
4688 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4689
pastarmovj89f7ee12016-09-20 14:58:134690 if syslog_files:
4691 return [output_api.PresubmitPromptWarning(
4692 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4693 ' calls.\nFiles to check:\n', items=syslog_files)]
4694 return []
4695
4696
[email protected]1f7b4172010-01-28 01:17:344697def CheckChangeOnUpload(input_api, output_api):
4698 results = []
4699 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474700 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284701 results.extend(
jam93a6ee792017-02-08 23:59:224702 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194703 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224704 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134705 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164706 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534707 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194708 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274709 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544710 return results
[email protected]ca8d1982009-02-19 16:33:124711
4712
[email protected]1bfb8322014-04-23 01:02:414713def GetTryServerMasterForBot(bot):
4714 """Returns the Try Server master for the given bot.
4715
[email protected]0bb112362014-07-26 04:38:324716 It tries to guess the master from the bot name, but may still fail
4717 and return None. There is no longer a default master.
4718 """
4719 # Potentially ambiguous bot names are listed explicitly.
4720 master_map = {
tandriie5587792016-07-14 00:34:504721 'chromium_presubmit': 'master.tryserver.chromium.linux',
4722 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414723 }
[email protected]0bb112362014-07-26 04:38:324724 master = master_map.get(bot)
4725 if not master:
wnwen4fbaab82016-05-25 12:54:364726 if 'android' in bot:
tandriie5587792016-07-14 00:34:504727 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364728 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504729 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324730 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504731 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324732 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504733 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324734 return master
[email protected]1bfb8322014-04-23 01:02:414735
4736
[email protected]ca8d1982009-02-19 16:33:124737def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544738 results = []
[email protected]1f7b4172010-01-28 01:17:344739 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574740 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544741 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274742 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344743 input_api,
4744 output_api,
[email protected]2fdd1f362013-01-16 03:56:034745 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274746
jam93a6ee792017-02-08 23:59:224747 results.extend(
4748 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544749 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4750 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384751 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4752 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414753 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4754 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544755 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144756
4757
4758def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144759 import os
4760 import sys
4761 from io import StringIO
4762
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144763 new_or_added_paths = set(f.LocalPath()
4764 for f in input_api.AffectedFiles()
4765 if (f.Action() == 'A' or f.Action() == 'M'))
4766 removed_paths = set(f.LocalPath()
4767 for f in input_api.AffectedFiles(include_deletes=True)
4768 if f.Action() == 'D')
4769
4770 affected_grds = [f for f in input_api.AffectedFiles()
4771 if (f.LocalPath().endswith('.grd') or
4772 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164773 if not affected_grds:
4774 return []
4775
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144776 affected_png_paths = [f.AbsoluteLocalPath()
4777 for f in input_api.AffectedFiles()
4778 if (f.LocalPath().endswith('.png'))]
4779
4780 # Check for screenshots. Developers can upload screenshots using
4781 # tools/translation/upload_screenshots.py which finds and uploads
4782 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4783 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4784 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4785 #
4786 # The logic here is as follows:
4787 #
4788 # - If the CL has a .png file under the screenshots directory for a grd
4789 # file, warn the developer. Actual images should never be checked into the
4790 # Chrome repo.
4791 #
4792 # - If the CL contains modified or new messages in grd files and doesn't
4793 # contain the corresponding .sha1 files, warn the developer to add images
4794 # and upload them via tools/translation/upload_screenshots.py.
4795 #
4796 # - If the CL contains modified or new messages in grd files and the
4797 # corresponding .sha1 files, everything looks good.
4798 #
4799 # - If the CL contains removed messages in grd files but the corresponding
4800 # .sha1 files aren't removed, warn the developer to remove them.
4801 unnecessary_screenshots = []
4802 missing_sha1 = []
4803 unnecessary_sha1_files = []
4804
4805
4806 def _CheckScreenshotAdded(screenshots_dir, message_id):
4807 sha1_path = input_api.os_path.join(
4808 screenshots_dir, message_id + '.png.sha1')
4809 if sha1_path not in new_or_added_paths:
4810 missing_sha1.append(sha1_path)
4811
4812
4813 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4814 sha1_path = input_api.os_path.join(
4815 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034816 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144817 unnecessary_sha1_files.append(sha1_path)
4818
meacer8c0d3832019-12-26 21:46:164819 try:
4820 old_sys_path = sys.path
4821 sys.path = sys.path + [input_api.os_path.join(
4822 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4823 from helper import grd_helper
4824 finally:
4825 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144826
4827 for f in affected_grds:
4828 file_path = f.LocalPath()
4829 old_id_to_msg_map = {}
4830 new_id_to_msg_map = {}
Mustafa Emre Acerd697ac92020-02-06 19:03:384831 # Note that this code doesn't check if the file has been deleted. This is
4832 # OK because it only uses the old and new file contents and doesn't load
4833 # the file via its path.
4834 # It's also possible that a file's content refers to a renamed or deleted
4835 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
4836 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
4837 # .grdp files.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144838 if file_path.endswith('.grdp'):
4839 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584840 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394841 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144842 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584843 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394844 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144845 else:
meacerff8a9b62019-12-10 19:43:584846 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144847 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584848 old_id_to_msg_map = grd_helper.GetGrdMessages(
4849 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144850 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584851 new_id_to_msg_map = grd_helper.GetGrdMessages(
4852 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144853
4854 # Compute added, removed and modified message IDs.
4855 old_ids = set(old_id_to_msg_map)
4856 new_ids = set(new_id_to_msg_map)
4857 added_ids = new_ids - old_ids
4858 removed_ids = old_ids - new_ids
4859 modified_ids = set([])
4860 for key in old_ids.intersection(new_ids):
4861 if (old_id_to_msg_map[key].FormatXml()
4862 != new_id_to_msg_map[key].FormatXml()):
4863 modified_ids.add(key)
4864
4865 grd_name, ext = input_api.os_path.splitext(
4866 input_api.os_path.basename(file_path))
4867 screenshots_dir = input_api.os_path.join(
4868 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4869
4870 # Check the screenshot directory for .png files. Warn if there is any.
4871 for png_path in affected_png_paths:
4872 if png_path.startswith(screenshots_dir):
4873 unnecessary_screenshots.append(png_path)
4874
4875 for added_id in added_ids:
4876 _CheckScreenshotAdded(screenshots_dir, added_id)
4877
4878 for modified_id in modified_ids:
4879 _CheckScreenshotAdded(screenshots_dir, modified_id)
4880
4881 for removed_id in removed_ids:
4882 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4883
4884 results = []
4885 if unnecessary_screenshots:
4886 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394887 'Do not include actual screenshots in the changelist. Run '
4888 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144889 sorted(unnecessary_screenshots)))
4890
4891 if missing_sha1:
4892 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394893 'You are adding or modifying UI strings.\n'
4894 'To ensure the best translations, take screenshots of the relevant UI '
4895 '(https://g.co/chrome/translation) and add these files to your '
4896 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144897
4898 if unnecessary_sha1_files:
4899 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394900 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144901 sorted(unnecessary_sha1_files)))
4902
4903 return results
Mustafa Emre Acer51f2f742020-03-09 19:41:124904
4905
4906def _CheckTranslationExpectations(input_api, output_api,
4907 repo_root=None,
4908 translation_expectations_path=None,
4909 grd_files=None):
4910 import sys
4911 affected_grds = [f for f in input_api.AffectedFiles()
4912 if (f.LocalPath().endswith('.grd') or
4913 f.LocalPath().endswith('.grdp'))]
4914 if not affected_grds:
4915 return []
4916
4917 try:
4918 old_sys_path = sys.path
4919 sys.path = sys.path + [
4920 input_api.os_path.join(
4921 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4922 from helper import git_helper
4923 from helper import translation_helper
4924 finally:
4925 sys.path = old_sys_path
4926
4927 # Check that translation expectations can be parsed and we can get a list of
4928 # translatable grd files. |repo_root| and |translation_expectations_path| are
4929 # only passed by tests.
4930 if not repo_root:
4931 repo_root = input_api.PresubmitLocalPath()
4932 if not translation_expectations_path:
4933 translation_expectations_path = input_api.os_path.join(
4934 repo_root, 'tools', 'gritsettings',
4935 'translation_expectations.pyl')
4936 if not grd_files:
4937 grd_files = git_helper.list_grds_in_repository(repo_root)
4938
4939 try:
4940 translation_helper.get_translatable_grds(repo_root, grd_files,
4941 translation_expectations_path)
4942 except Exception as e:
4943 return [output_api.PresubmitNotifyResult(
4944 'Failed to get a list of translatable grd files. This happens when:\n'
4945 ' - One of the modified grd or grdp files cannot be parsed or\n'
4946 ' - %s is not updated.\n'
4947 'Stack:\n%s' % (translation_expectations_path, str(e)))]
4948 return []