blob: 2169ec3c0e08a071a296ecfbbd746421db9e7961 [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$",
Egor Paskoce145c42018-09-28 19:31:0425 r".+[\\/]pnacl_shim\.c$",
26 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
27 r"^chrome[\\/]browser[\\/]resources[\\/]pdf[\\/]index.js",
28 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$',
[email protected]06e6d0ff2012-12-11 01:36:4462)
[email protected]ca8d1982009-02-19 16:33:1263
Daniel Bratell609102be2019-03-27 20:53:2164_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1565
[email protected]eea609a2011-11-18 13:10:1266_TEST_ONLY_WARNING = (
67 'You might be calling functions intended only for testing from\n'
68 'production code. It is OK to ignore this warning if you know what\n'
69 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5870 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1271
72
[email protected]cf9b78f2012-11-14 11:40:2873_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4074 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2175 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
76 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2877
wnwenbdc444e2016-05-25 13:44:1578
Daniel Bratell609102be2019-03-27 20:53:2179# Format: Sequence of tuples containing:
80# * String pattern or, if starting with a slash, a regular expression.
81# * Sequence of strings to show when the pattern matches.
82# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:4183_BANNED_JAVA_FUNCTIONS = (
84 (
85 'StrictMode.allowThreadDiskReads()',
86 (
87 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
88 'directly.',
89 ),
90 False,
91 ),
92 (
93 'StrictMode.allowThreadDiskWrites()',
94 (
95 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
96 'directly.',
97 ),
98 False,
99 ),
100)
101
Daniel Bratell609102be2019-03-27 20:53:21102# Format: Sequence of tuples containing:
103# * String pattern or, if starting with a slash, a regular expression.
104# * Sequence of strings to show when the pattern matches.
105# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59106_BANNED_OBJC_FUNCTIONS = (
107 (
108 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20109 (
110 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59111 'prohibited. Please use CrTrackingArea instead.',
112 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
113 ),
114 False,
115 ),
116 (
[email protected]eaae1972014-04-16 04:17:26117 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20118 (
119 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59120 'instead.',
121 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
122 ),
123 False,
124 ),
125 (
126 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20127 (
128 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59129 'Please use |convertPoint:(point) fromView:nil| instead.',
130 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
131 ),
132 True,
133 ),
134 (
135 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20136 (
137 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59138 'Please use |convertPoint:(point) toView:nil| instead.',
139 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
140 ),
141 True,
142 ),
143 (
144 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20145 (
146 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59147 'Please use |convertRect:(point) fromView:nil| instead.',
148 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
149 ),
150 True,
151 ),
152 (
153 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20154 (
155 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59156 'Please use |convertRect:(point) toView:nil| instead.',
157 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
158 ),
159 True,
160 ),
161 (
162 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20163 (
164 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59165 'Please use |convertSize:(point) fromView:nil| instead.',
166 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
167 ),
168 True,
169 ),
170 (
171 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20172 (
173 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59174 'Please use |convertSize:(point) toView:nil| instead.',
175 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
176 ),
177 True,
178 ),
jif65398702016-10-27 10:19:48179 (
180 r"/\s+UTF8String\s*]",
181 (
182 'The use of -[NSString UTF8String] is dangerous as it can return null',
183 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
184 'Please use |SysNSStringToUTF8| instead.',
185 ),
186 True,
187 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34188 (
189 r'__unsafe_unretained',
190 (
191 'The use of __unsafe_unretained is almost certainly wrong, unless',
192 'when interacting with NSFastEnumeration or NSInvocation.',
193 'Please use __weak in files build with ARC, nothing otherwise.',
194 ),
195 False,
196 ),
Avi Drissman7382afa02019-04-29 23:27:13197 (
198 'freeWhenDone:NO',
199 (
200 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
201 'Foundation types is prohibited.',
202 ),
203 True,
204 ),
[email protected]127f18ec2012-06-16 05:05:59205)
206
Daniel Bratell609102be2019-03-27 20:53:21207# Format: Sequence of tuples containing:
208# * String pattern or, if starting with a slash, a regular expression.
209# * Sequence of strings to show when the pattern matches.
210# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54211_BANNED_IOS_OBJC_FUNCTIONS = (
212 (
213 r'/\bTEST[(]',
214 (
215 'TEST() macro should not be used in Objective-C++ code as it does not ',
216 'drain the autorelease pool at the end of the test. Use TEST_F() ',
217 'macro instead with a fixture inheriting from PlatformTest (or a ',
218 'typedef).'
219 ),
220 True,
221 ),
222 (
223 r'/\btesting::Test\b',
224 (
225 'testing::Test should not be used in Objective-C++ code as it does ',
226 'not drain the autorelease pool at the end of the test. Use ',
227 'PlatformTest instead.'
228 ),
229 True,
230 ),
231)
232
Peter K. Lee6c03ccff2019-07-15 14:40:05233# Format: Sequence of tuples containing:
234# * String pattern or, if starting with a slash, a regular expression.
235# * Sequence of strings to show when the pattern matches.
236# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
237_BANNED_IOS_EGTEST_FUNCTIONS = (
238 (
239 r'/\bEXPECT_OCMOCK_VERIFY\b',
240 (
241 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
242 'it is meant for GTests. Use [mock verify] instead.'
243 ),
244 True,
245 ),
246)
247
danakj7a2b7082019-05-21 21:13:51248# Directories that contain deprecated Bind() or Callback types.
249# Find sub-directories from a given directory by running:
250# for i in `find . -maxdepth 1 -type d`; do
251# echo "-- $i"
252# (cd $i; git grep -P 'base::(Bind\(|(Callback<|Closure))'|wc -l)
253# done
254#
255# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
256# when they have been converted to modern callback types (OnceCallback,
257# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
258# checks for them and prevent regressions.
259_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
260 '^android_webview/browser/',
261 '^apps/',
262 '^ash/',
263 '^base/',
264 '^base/callback.h', # Intentional.
265 '^chrome/app/',
266 '^chrome/browser/',
267 '^chrome/chrome_elf/',
268 '^chrome/chrome_watcher/',
269 '^chrome/common/',
270 '^chrome/installer/',
271 '^chrome/notification_helper/',
272 '^chrome/renderer/',
273 '^chrome/services/',
274 '^chrome/test/',
275 '^chrome/tools/',
276 '^chrome/utility/',
277 '^chromecast/app/',
278 '^chromecast/browser/',
279 '^chromecast/crash/',
280 '^chromecast/media/',
281 '^chromecast/metrics/',
282 '^chromecast/net/',
283 '^chromeos/attestation/',
284 '^chromeos/audio/',
285 '^chromeos/components/',
286 '^chromeos/cryptohome/',
287 '^chromeos/dbus/',
288 '^chromeos/geolocation/',
289 '^chromeos/login/',
290 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51291 '^chromeos/process_proxy/',
292 '^chromeos/services/',
293 '^chromeos/settings/',
294 '^chromeos/timezone/',
295 '^chromeos/tpm/',
296 '^components/arc/',
297 '^components/assist_ranker/',
298 '^components/autofill/',
299 '^components/autofill_assistant/',
300 '^components/bookmarks/',
301 '^components/browser_sync/',
302 '^components/browser_watcher/',
303 '^components/browsing_data/',
304 '^components/cast_channel/',
305 '^components/certificate_transparency/',
306 '^components/chromeos_camera/',
307 '^components/component_updater/',
308 '^components/content_settings/',
309 '^components/crash/',
310 '^components/cronet/',
311 '^components/data_reduction_proxy/',
312 '^components/discardable_memory/',
313 '^components/dom_distiller/',
314 '^components/domain_reliability/',
315 '^components/download/',
316 '^components/drive/',
317 '^components/exo/',
318 '^components/favicon/',
319 '^components/feature_engagement/',
320 '^components/feedback/',
321 '^components/flags_ui/',
322 '^components/gcm_driver/',
323 '^components/google/',
324 '^components/guest_view/',
325 '^components/heap_profiling/',
326 '^components/history/',
327 '^components/image_fetcher/',
328 '^components/invalidation/',
329 '^components/keyed_service/',
330 '^components/login/',
331 '^components/metrics/',
332 '^components/metrics_services_manager/',
333 '^components/nacl/',
334 '^components/navigation_interception/',
335 '^components/net_log/',
336 '^components/network_time/',
337 '^components/ntp_snippets/',
338 '^components/ntp_tiles/',
339 '^components/offline_items_collection/',
340 '^components/offline_pages/',
341 '^components/omnibox/',
342 '^components/ownership/',
343 '^components/pairing/',
344 '^components/password_manager/',
345 '^components/payments/',
346 '^components/plugins/',
347 '^components/policy/',
348 '^components/pref_registry/',
349 '^components/prefs/',
danakj7a2b7082019-05-21 21:13:51350 '^components/proxy_config/',
351 '^components/quirks/',
352 '^components/rappor/',
353 '^components/remote_cocoa/',
354 '^components/renderer_context_menu/',
355 '^components/rlz/',
356 '^components/safe_browsing/',
357 '^components/search_engines/',
358 '^components/search_provider_logos/',
359 '^components/security_interstitials/',
360 '^components/security_state/',
361 '^components/services/',
362 '^components/sessions/',
363 '^components/signin/',
364 '^components/ssl_errors/',
365 '^components/storage_monitor/',
366 '^components/subresource_filter/',
367 '^components/suggestions/',
368 '^components/supervised_user_error_page/',
369 '^components/sync/',
370 '^components/sync_bookmarks/',
371 '^components/sync_device_info/',
372 '^components/sync_preferences/',
373 '^components/sync_sessions/',
374 '^components/test/',
375 '^components/tracing/',
376 '^components/translate/',
377 '^components/ukm/',
378 '^components/update_client/',
379 '^components/upload_list/',
380 '^components/variations/',
381 '^components/visitedlink/',
382 '^components/web_cache/',
383 '^components/web_resource/',
danakj7a2b7082019-05-21 21:13:51384 '^components/webcrypto/',
385 '^components/webdata/',
386 '^components/webdata_services/',
387 '^components/wifi/',
388 '^components/zoom/',
389 '^content/app/',
390 '^content/browser/',
391 '^content/child/',
392 '^content/common/',
393 '^content/public/',
394 '^content/renderer/android/',
395 '^content/renderer/fetchers/',
396 '^content/renderer/image_downloader/',
397 '^content/renderer/input/',
398 '^content/renderer/java/',
399 '^content/renderer/media/',
400 '^content/renderer/media_capture_from_element/',
401 '^content/renderer/media_recorder/',
402 '^content/renderer/p2p/',
403 '^content/renderer/pepper/',
404 '^content/renderer/service_worker/',
405 '^content/renderer/worker/',
406 '^content/test/',
407 '^content/utility/',
408 '^dbus/',
409 '^device/base/',
410 '^device/bluetooth/',
411 '^device/fido/',
412 '^device/gamepad/',
413 '^device/udev_linux/',
414 '^device/vr/',
415 '^extensions/',
416 '^gin/',
417 '^google_apis/dive/',
418 '^google_apis/gaia/',
419 '^google_apis/gcm/',
420 '^headless/',
421 '^ios/chrome/',
422 '^ios/components/',
423 '^ios/net/',
424 '^ios/web/',
425 '^ios/web_view/',
426 '^ipc/',
427 '^media/audio/',
428 '^media/base/',
429 '^media/capture/',
430 '^media/cast/',
431 '^media/cdm/',
432 '^media/device_monitors/',
433 '^media/ffmpeg/',
434 '^media/filters/',
435 '^media/formats/',
436 '^media/gpu/',
437 '^media/mojo/',
438 '^media/muxers/',
439 '^media/remoting/',
440 '^media/renderers/',
441 '^media/test/',
442 '^mojo/core/',
443 '^mojo/public/',
444 '^net/',
445 '^ppapi/proxy/',
446 '^ppapi/shared_impl/',
447 '^ppapi/tests/',
448 '^ppapi/thunk/',
449 '^remoting/base/',
450 '^remoting/client/',
451 '^remoting/codec/',
452 '^remoting/host/',
453 '^remoting/internal/',
454 '^remoting/ios/',
455 '^remoting/protocol/',
456 '^remoting/signaling/',
457 '^remoting/test/',
458 '^sandbox/linux/',
459 '^sandbox/win/',
460 '^services/',
461 '^storage/browser/',
462 '^testing/gmock_mutant.h',
463 '^testing/libfuzzer/',
464 '^third_party/blink/',
465 '^third_party/crashpad/crashpad/test/gtest_main.cc',
466 '^third_party/leveldatabase/leveldb_chrome.cc',
467 '^third_party/boringssl/gtest_main_chromium.cc',
468 '^third_party/cacheinvalidation/overrides/' +
469 'google/cacheinvalidation/deps/callback.h',
470 '^third_party/libaddressinput/chromium/chrome_address_validator.cc',
471 '^third_party/zlib/google/',
472 '^tools/android/',
473 '^tools/clang/base_bind_rewriters/', # Intentional.
474 '^tools/gdb/gdb_chrome.py', # Intentional.
475 '^ui/accelerated_widget_mac/',
476 '^ui/android/',
477 '^ui/aura/',
478 '^ui/base/',
479 '^ui/compositor/',
480 '^ui/display/',
481 '^ui/events/',
482 '^ui/gfx/',
483 '^ui/message_center/',
danakj7a2b7082019-05-21 21:13:51484 '^ui/snapshot/',
485 '^ui/views_content_client/',
486 '^ui/wm/',
487))
[email protected]127f18ec2012-06-16 05:05:59488
Daniel Bratell609102be2019-03-27 20:53:21489# Format: Sequence of tuples containing:
490# * String pattern or, if starting with a slash, a regular expression.
491# * Sequence of strings to show when the pattern matches.
492# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
493# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59494_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20495 (
Dave Tapuska98199b612019-07-10 13:30:44496 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53497 (
498 'New code should not use NULL. Use nullptr instead.',
499 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20500 False,
thomasandersone7caaa9b2017-03-29 19:22:53501 (),
502 ),
Antonio Gomes07300d02019-03-13 20:59:57503 # Make sure that gtest's FRIEND_TEST() macro is not used; the
504 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
505 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53506 (
[email protected]23e6cbc2012-06-16 18:51:20507 'FRIEND_TEST(',
508 (
[email protected]e3c945502012-06-26 20:01:49509 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20510 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
511 ),
512 False,
[email protected]7345da02012-11-27 14:31:49513 (),
[email protected]23e6cbc2012-06-16 18:51:20514 ),
515 (
Dave Tapuska98199b612019-07-10 13:30:44516 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53517 (
518 'Chrome clients wishing to select events on X windows should use',
519 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
520 'you are selecting events from the GPU process, or if you are using',
521 'an XDisplay other than gfx::GetXDisplay().',
522 ),
523 True,
524 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40525 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04526 r"^ui[\\/]gl[\\/].*\.cc$",
527 r"^media[\\/]gpu[\\/].*\.cc$",
528 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53529 ),
530 ),
531 (
Dave Tapuska98199b612019-07-10 13:30:44532 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20533 (
thomasanderson11aa41d2017-06-08 22:22:38534 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20535 ),
536 True,
537 (
Egor Paskoce145c42018-09-28 19:31:04538 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
539 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
540 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20541 ),
542 ),
543 (
tomhudsone2c14d552016-05-26 17:07:46544 'setMatrixClip',
545 (
546 'Overriding setMatrixClip() is prohibited; ',
547 'the base function is deprecated. ',
548 ),
549 True,
550 (),
551 ),
552 (
[email protected]52657f62013-05-20 05:30:31553 'SkRefPtr',
554 (
555 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22556 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31557 ),
558 True,
559 (),
560 ),
561 (
562 'SkAutoRef',
563 (
564 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22565 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31566 ),
567 True,
568 (),
569 ),
570 (
571 'SkAutoTUnref',
572 (
573 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22574 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31575 ),
576 True,
577 (),
578 ),
579 (
580 'SkAutoUnref',
581 (
582 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
583 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22584 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31585 ),
586 True,
587 (),
588 ),
[email protected]d89eec82013-12-03 14:10:59589 (
590 r'/HANDLE_EINTR\(.*close',
591 (
592 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
593 'descriptor will be closed, and it is incorrect to retry the close.',
594 'Either call close directly and ignore its return value, or wrap close',
595 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
596 ),
597 True,
598 (),
599 ),
600 (
601 r'/IGNORE_EINTR\((?!.*close)',
602 (
603 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
604 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
605 ),
606 True,
607 (
608 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04609 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
610 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59611 ),
612 ),
[email protected]ec5b3f02014-04-04 18:43:43613 (
614 r'/v8::Extension\(',
615 (
616 'Do not introduce new v8::Extensions into the code base, use',
617 'gin::Wrappable instead. See http://crbug.com/334679',
618 ),
619 True,
[email protected]f55c90ee62014-04-12 00:50:03620 (
Egor Paskoce145c42018-09-28 19:31:04621 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03622 ),
[email protected]ec5b3f02014-04-04 18:43:43623 ),
skyostilf9469f72015-04-20 10:38:52624 (
jame2d1a952016-04-02 00:27:10625 '#pragma comment(lib,',
626 (
627 'Specify libraries to link with in build files and not in the source.',
628 ),
629 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41630 (
tzik3f295992018-12-04 20:32:23631 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04632 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41633 ),
jame2d1a952016-04-02 00:27:10634 ),
fdorayc4ac18d2017-05-01 21:39:59635 (
Gabriel Charette7cc6c432018-04-25 20:52:02636 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59637 (
638 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
639 ),
640 False,
641 (),
642 ),
643 (
Gabriel Charette7cc6c432018-04-25 20:52:02644 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59645 (
646 'Consider using THREAD_CHECKER macros instead of the class directly.',
647 ),
648 False,
649 (),
650 ),
dbeamb6f4fde2017-06-15 04:03:06651 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06652 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
653 (
654 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
655 'deprecated (http://crbug.com/634507). Please avoid converting away',
656 'from the Time types in Chromium code, especially if any math is',
657 'being done on time values. For interfacing with platform/library',
658 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
659 'type converter methods instead. For faking TimeXXX values (for unit',
660 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
661 'other use cases, please contact base/time/OWNERS.',
662 ),
663 False,
664 (),
665 ),
666 (
dbeamb6f4fde2017-06-15 04:03:06667 'CallJavascriptFunctionUnsafe',
668 (
669 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
670 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
671 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
672 ),
673 False,
674 (
Egor Paskoce145c42018-09-28 19:31:04675 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
676 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
677 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06678 ),
679 ),
dskiba1474c2bfd62017-07-20 02:19:24680 (
681 'leveldb::DB::Open',
682 (
683 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
684 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
685 "Chrome's tracing, making their memory usage visible.",
686 ),
687 True,
688 (
689 r'^third_party/leveldatabase/.*\.(cc|h)$',
690 ),
Gabriel Charette0592c3a2017-07-26 12:02:04691 ),
692 (
Chris Mumfordc38afb62017-10-09 17:55:08693 'leveldb::NewMemEnv',
694 (
695 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58696 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
697 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08698 ),
699 True,
700 (
701 r'^third_party/leveldatabase/.*\.(cc|h)$',
702 ),
703 ),
704 (
Gabriel Charetted9839bc2017-07-29 14:17:47705 'RunLoop::QuitCurrent',
706 (
Robert Liao64b7ab22017-08-04 23:03:43707 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
708 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47709 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41710 False,
Gabriel Charetted9839bc2017-07-29 14:17:47711 (),
Gabriel Charettea44975052017-08-21 23:14:04712 ),
713 (
714 'base::ScopedMockTimeMessageLoopTaskRunner',
715 (
Gabriel Charette87cc1af2018-04-25 20:52:51716 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11717 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51718 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
719 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
720 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04721 ),
Gabriel Charette87cc1af2018-04-25 20:52:51722 False,
Gabriel Charettea44975052017-08-21 23:14:04723 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57724 ),
725 (
Dave Tapuska98199b612019-07-10 13:30:44726 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57727 (
728 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02729 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57730 ),
731 True,
732 (),
Francois Doray43670e32017-09-27 12:40:38733 ),
734 (
Peter Kasting991618a62019-06-17 22:00:09735 r'/\bstd::stoi\b',
736 (
737 'std::stoi uses exceptions to communicate results. ',
738 'Use base::StringToInt() instead.',
739 ),
740 True,
741 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
742 ),
743 (
744 r'/\bstd::stol\b',
745 (
746 'std::stol uses exceptions to communicate results. ',
747 'Use base::StringToInt() instead.',
748 ),
749 True,
750 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
751 ),
752 (
753 r'/\bstd::stoul\b',
754 (
755 'std::stoul uses exceptions to communicate results. ',
756 'Use base::StringToUint() instead.',
757 ),
758 True,
759 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
760 ),
761 (
762 r'/\bstd::stoll\b',
763 (
764 'std::stoll uses exceptions to communicate results. ',
765 'Use base::StringToInt64() instead.',
766 ),
767 True,
768 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
769 ),
770 (
771 r'/\bstd::stoull\b',
772 (
773 'std::stoull uses exceptions to communicate results. ',
774 'Use base::StringToUint64() instead.',
775 ),
776 True,
777 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
778 ),
779 (
780 r'/\bstd::stof\b',
781 (
782 'std::stof uses exceptions to communicate results. ',
783 'For locale-independent values, e.g. reading numbers from disk',
784 'profiles, use base::StringToDouble().',
785 'For user-visible values, parse using ICU.',
786 ),
787 True,
788 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
789 ),
790 (
791 r'/\bstd::stod\b',
792 (
793 'std::stod uses exceptions to communicate results. ',
794 'For locale-independent values, e.g. reading numbers from disk',
795 'profiles, use base::StringToDouble().',
796 'For user-visible values, parse using ICU.',
797 ),
798 True,
799 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
800 ),
801 (
802 r'/\bstd::stold\b',
803 (
804 'std::stold uses exceptions to communicate results. ',
805 'For locale-independent values, e.g. reading numbers from disk',
806 'profiles, use base::StringToDouble().',
807 'For user-visible values, parse using ICU.',
808 ),
809 True,
810 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
811 ),
812 (
Daniel Bratell69334cc2019-03-26 11:07:45813 r'/\bstd::to_string\b',
814 (
815 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09816 'For locale-independent strings, e.g. writing numbers to disk',
817 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45818 'For user-visible strings, use base::FormatNumber() and',
819 'the related functions in base/i18n/number_formatting.h.',
820 ),
Peter Kasting991618a62019-06-17 22:00:09821 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21822 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45823 ),
824 (
825 r'/\bstd::shared_ptr\b',
826 (
827 'std::shared_ptr should not be used. Use scoped_refptr instead.',
828 ),
829 True,
Daniel Bratell609102be2019-03-27 20:53:21830 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
831 ),
832 (
Peter Kasting991618a62019-06-17 22:00:09833 r'/\bstd::weak_ptr\b',
834 (
835 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
836 ),
837 True,
838 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
839 ),
840 (
Daniel Bratell609102be2019-03-27 20:53:21841 r'/\blong long\b',
842 (
843 'long long is banned. Use stdint.h if you need a 64 bit number.',
844 ),
845 False, # Only a warning since it is already used.
846 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
847 ),
848 (
849 r'/\bstd::bind\b',
850 (
851 'std::bind is banned because of lifetime risks.',
852 'Use base::BindOnce or base::BindRepeating instead.',
853 ),
854 True,
855 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
856 ),
857 (
858 r'/\b#include <chrono>\b',
859 (
860 '<chrono> overlaps with Time APIs in base. Keep using',
861 'base classes.',
862 ),
863 True,
864 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
865 ),
866 (
867 r'/\b#include <exception>\b',
868 (
869 'Exceptions are banned and disabled in Chromium.',
870 ),
871 True,
872 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
873 ),
874 (
875 r'/\bstd::function\b',
876 (
877 'std::function is banned. Instead use base::Callback which directly',
878 'supports Chromium\'s weak pointers, ref counting and more.',
879 ),
Peter Kasting991618a62019-06-17 22:00:09880 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21881 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
882 ),
883 (
884 r'/\b#include <random>\b',
885 (
886 'Do not use any random number engines from <random>. Instead',
887 'use base::RandomBitGenerator.',
888 ),
889 True,
890 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
891 ),
892 (
893 r'/\bstd::ratio\b',
894 (
895 'std::ratio is banned by the Google Style Guide.',
896 ),
897 True,
898 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45899 ),
900 (
Francois Doray43670e32017-09-27 12:40:38901 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
902 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
903 (
904 'Use the new API in base/threading/thread_restrictions.h.',
905 ),
Gabriel Charette04b138f2018-08-06 00:03:22906 False,
Francois Doray43670e32017-09-27 12:40:38907 (),
908 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38909 (
danakj7a2b7082019-05-21 21:13:51910 r'/\bbase::Bind\(',
911 (
912 'Please use base::Bind{Once,Repeating} instead',
913 'of base::Bind. (crbug.com/714018)',
914 ),
915 False,
916 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
917 ),
918 (
919 r'/\bbase::Callback[<:]',
920 (
921 'Please use base::{Once,Repeating}Callback instead',
922 'of base::Callback. (crbug.com/714018)',
923 ),
924 False,
925 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
926 ),
927 (
928 r'/\bbase::Closure\b',
929 (
930 'Please use base::{Once,Repeating}Closure instead',
931 'of base::Closure. (crbug.com/714018)',
932 ),
933 False,
934 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
935 ),
936 (
Alex Ilin5929abe32019-04-03 17:09:34937 r'/base::SharedMemory(|Handle)',
Alex Ilin63058f62019-03-28 19:29:45938 (
939 'base::SharedMemory is deprecated. Please use',
940 '{Writable,ReadOnly}SharedMemoryRegion instead.',
941 ),
942 False,
943 (),
944 ),
945 (
Michael Giuffrida7f93d6922019-04-19 14:39:58946 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19947 (
948 'RunMessageLoop is deprecated, use RunLoop instead.',
949 ),
950 False,
951 (),
952 ),
953 (
Dave Tapuska98199b612019-07-10 13:30:44954 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19955 (
956 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
957 ),
958 False,
959 (),
960 ),
961 (
Dave Tapuska98199b612019-07-10 13:30:44962 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19963 (
964 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
965 "if you're convinced you need this.",
966 ),
967 False,
968 (),
969 ),
970 (
Dave Tapuska98199b612019-07-10 13:30:44971 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19972 (
973 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04974 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19975 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
976 'async events instead of flushing threads.',
977 ),
978 False,
979 (),
980 ),
981 (
982 r'MessageLoopRunner',
983 (
984 'MessageLoopRunner is deprecated, use RunLoop instead.',
985 ),
986 False,
987 (),
988 ),
989 (
Dave Tapuska98199b612019-07-10 13:30:44990 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19991 (
992 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
993 "gab@ if you found a use case where this is the only solution.",
994 ),
995 False,
996 (),
997 ),
998 (
Victor Costane48a2e82019-03-15 22:02:34999 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161000 (
Victor Costane48a2e82019-03-15 22:02:341001 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161002 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1003 ),
1004 True,
1005 (
1006 r'^sql/initialization\.(cc|h)$',
1007 r'^third_party/sqlite/.*\.(c|cc|h)$',
1008 ),
1009 ),
Matt Menke7f520a82018-03-28 21:38:371010 (
1011 'net::URLFetcher',
1012 (
1013 'net::URLFetcher should no longer be used in content embedders. ',
1014 'Instead, use network::SimpleURLLoader instead, which supports ',
1015 'an out-of-process network stack. ',
1016 'net::URLFetcher may still be used in binaries that do not embed',
1017 'content.',
1018 ),
Matt Menke59716d02018-04-05 12:45:531019 False,
Matt Menke7f520a82018-03-28 21:38:371020 (
Egor Paskoce145c42018-09-28 19:31:041021 r'^ios[\\/].*\.(cc|h)$',
1022 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:371023 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:041024 r'^net[\\/].*\.(cc|h)$',
1025 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi347f6992019-07-11 00:29:201026 r'^fuchsia/engine/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:371027 ),
1028 ),
jdoerried7d10ab2018-04-27 10:46:131029 (
Dave Tapuska98199b612019-07-10 13:30:441030 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471031 (
1032 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1033 'base::RandomShuffle instead.'
1034 ),
1035 True,
1036 (),
1037 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241038 (
1039 'ios/web/public/test/http_server',
1040 (
1041 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1042 ),
1043 False,
1044 (),
1045 ),
Robert Liao764c9492019-01-24 18:46:281046 (
1047 'GetAddressOf',
1048 (
1049 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
1050 'implicated in a few leaks. Use operator& instead.'
1051 ),
1052 True,
1053 (),
1054 ),
Antonio Gomes07300d02019-03-13 20:59:571055 (
1056 'DEFINE_TYPE_CASTS',
1057 (
1058 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1059 '//third_party/blink/renderer/platform/casting.h.'
1060 ),
1061 True,
1062 (
1063 r'^third_party/blink/renderer/.*\.(cc|h)$',
1064 ),
1065 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381066 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371067 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381068 (
1069 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1070 ),
1071 True,
1072 (),
1073 ),
Ben Lewisa9514602019-04-29 17:53:051074 (
1075 'SHFileOperation',
1076 (
1077 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1078 'complex functions to achieve the same goals. Use IFileOperation for ',
1079 'any esoteric actions instead.'
1080 ),
1081 True,
1082 (),
1083 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181084 (
Cliff Smolinsky81951642019-04-30 21:39:511085 'StringFromGUID2',
1086 (
1087 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1088 'Use base::win::String16FromGUID instead.'
1089 ),
1090 True,
1091 (
1092 r'/base/win/win_util_unittest.cc'
1093 ),
1094 ),
1095 (
1096 'StringFromCLSID',
1097 (
1098 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1099 'Use base::win::String16FromGUID instead.'
1100 ),
1101 True,
1102 (
1103 r'/base/win/win_util_unittest.cc'
1104 ),
1105 ),
1106 (
Avi Drissman7382afa02019-04-29 23:27:131107 'kCFAllocatorNull',
1108 (
1109 'The use of kCFAllocatorNull with the NoCopy creation of ',
1110 'CoreFoundation types is prohibited.',
1111 ),
1112 True,
1113 (),
1114 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291115 (
1116 'mojo::ConvertTo',
1117 (
1118 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1119 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1120 'StringTraits if you would like to convert between custom types and',
1121 'the wire format of mojom types.'
1122 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221123 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291124 (
1125 r'^third_party/blink/.*\.(cc|h)$',
1126 r'^content/renderer/.*\.(cc|h)$',
1127 ),
1128 ),
[email protected]127f18ec2012-06-16 05:05:591129)
1130
wnwenbdc444e2016-05-25 13:44:151131
mlamouria82272622014-09-16 18:45:041132_IPC_ENUM_TRAITS_DEPRECATED = (
1133 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501134 'See http://www.chromium.org/Home/chromium-security/education/'
1135 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041136
Stephen Martinis97a394142018-06-07 23:06:051137_LONG_PATH_ERROR = (
1138 'Some files included in this CL have file names that are too long (> 200'
1139 ' characters). If committed, these files will cause issues on Windows. See'
1140 ' https://crbug.com/612667 for more details.'
1141)
1142
Shenghua Zhangbfaa38b82017-11-16 21:58:021143_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041144 r".*[\\/]BuildHooksAndroidImpl\.java",
1145 r".*[\\/]LicenseContentProvider\.java",
1146 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281147 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021148]
[email protected]127f18ec2012-06-16 05:05:591149
Sean Kau46e29bc2017-08-28 16:31:161150# These paths contain test data and other known invalid JSON files.
1151_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041152 r'test[\\/]data[\\/]',
1153 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1154 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041155 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431156 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161157]
1158
1159
[email protected]b00342e7f2013-03-26 16:21:541160_VALID_OS_MACROS = (
1161 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081162 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541163 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121164 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541165 'OS_BSD',
1166 'OS_CAT', # For testing.
1167 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041168 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541169 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371170 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541171 'OS_IOS',
1172 'OS_LINUX',
1173 'OS_MACOSX',
1174 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211175 'OS_NACL_NONSFI',
1176 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121177 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541178 'OS_OPENBSD',
1179 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371180 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541181 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541182 'OS_WIN',
1183)
1184
1185
agrievef32bcc72016-04-04 14:57:401186_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391187 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361188 'base/android/jni_generator/jni_generator.pydeps',
1189 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221190 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361191 'build/android/gyp/aar.pydeps',
1192 'build/android/gyp/aidl.pydeps',
1193 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381194 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361195 'build/android/gyp/bytecode_processor.pydeps',
1196 'build/android/gyp/compile_resources.pydeps',
Tibor Goldschwendt84ec04c2019-08-23 21:19:091197 'build/android/gyp/create_app_bundle_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361198 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1199 'build/android/gyp/copy_ex.pydeps',
1200 'build/android/gyp/create_app_bundle.pydeps',
1201 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361202 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221203 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361204 'build/android/gyp/create_tool_wrapper.pydeps',
1205 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591206 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361207 'build/android/gyp/dex.pydeps',
1208 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361209 'build/android/gyp/filter_zip.pydeps',
1210 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361211 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361212 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581213 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361214 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261215 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361216 'build/android/gyp/javac.pydeps',
1217 'build/android/gyp/jinja_template.pydeps',
1218 'build/android/gyp/lint.pydeps',
1219 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361220 'build/android/gyp/merge_manifest.pydeps',
1221 'build/android/gyp/prepare_resources.pydeps',
1222 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241223 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361224 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461225 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561226 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361227 'build/android/incremental_install/generate_android_manifest.pydeps',
1228 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221229 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401230 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041231 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361232 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411233 'chrome/android/features/create_stripped_java_factory.pydeps',
agrieve732db3a2016-04-26 19:18:191234 'net/tools/testserver/testserver.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021235 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401236]
1237
wnwenbdc444e2016-05-25 13:44:151238
agrievef32bcc72016-04-04 14:57:401239_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:401240 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Cole Winstanley7045a1b2018-08-27 23:37:291241 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421242 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1243 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
John Budorickbc3571aa2019-04-25 02:20:061244 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221245 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401246]
1247
wnwenbdc444e2016-05-25 13:44:151248
agrievef32bcc72016-04-04 14:57:401249_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1250
1251
Eric Boren6fd2b932018-01-25 15:05:081252# Bypass the AUTHORS check for these accounts.
1253_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291254 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1255 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081256 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321257 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591258 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451259 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591260 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221261 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041262 ) | set('%[email protected]' % s
1263 for s in ('chromium-autoroll',)
1264 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301265 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081266
1267
Daniel Bratell65b033262019-04-23 08:17:061268def _IsCPlusPlusFile(input_api, file_path):
1269 """Returns True if this file contains C++-like code (and not Python,
1270 Go, Java, MarkDown, ...)"""
1271
1272 ext = input_api.os_path.splitext(file_path)[1]
1273 # This list is compatible with CppChecker.IsCppFile but we should
1274 # consider adding ".c" to it. If we do that we can use this function
1275 # at more places in the code.
1276 return ext in (
1277 '.h',
1278 '.cc',
1279 '.cpp',
1280 '.m',
1281 '.mm',
1282 )
1283
1284def _IsCPlusPlusHeaderFile(input_api, file_path):
1285 return input_api.os_path.splitext(file_path)[1] == ".h"
1286
1287
1288def _IsJavaFile(input_api, file_path):
1289 return input_api.os_path.splitext(file_path)[1] == ".java"
1290
1291
1292def _IsProtoFile(input_api, file_path):
1293 return input_api.os_path.splitext(file_path)[1] == ".proto"
1294
[email protected]55459852011-08-10 15:17:191295def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1296 """Attempts to prevent use of functions intended only for testing in
1297 non-testing code. For now this is just a best-effort implementation
1298 that ignores header files and may have some false positives. A
1299 better implementation would probably need a proper C++ parser.
1300 """
1301 # We only scan .cc files and the like, as the declaration of
1302 # for-testing functions in header files are hard to distinguish from
1303 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491304 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191305
jochenc0d4808c2015-07-27 09:25:421306 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191307 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091308 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191309 exclusion_pattern = input_api.re.compile(
1310 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1311 base_function_pattern, base_function_pattern))
1312
1313 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441314 black_list = (_EXCLUDED_PATHS +
1315 _TEST_CODE_EXCLUDED_PATHS +
1316 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191317 return input_api.FilterSourceFile(
1318 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491319 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191320 black_list=black_list)
1321
1322 problems = []
1323 for f in input_api.AffectedSourceFiles(FilterFile):
1324 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241325 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031326 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461327 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031328 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191329 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031330 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191331
1332 if problems:
[email protected]f7051d52013-04-02 18:31:421333 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031334 else:
1335 return []
[email protected]55459852011-08-10 15:17:191336
1337
Vaclav Brozek7dbc28c2018-03-27 08:35:231338def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1339 """This is a simplified version of
1340 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1341 """
1342 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1343 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1344 name_pattern = r'ForTest(s|ing)?'
1345 # Describes an occurrence of "ForTest*" inside a // comment.
1346 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1347 # Catch calls.
1348 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1349 # Ignore definitions. (Comments are ignored separately.)
1350 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1351
1352 problems = []
1353 sources = lambda x: input_api.FilterSourceFile(
1354 x,
1355 black_list=(('(?i).*test', r'.*\/junit\/')
1356 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491357 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231358 )
1359 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1360 local_path = f.LocalPath()
1361 is_inside_javadoc = False
1362 for line_number, line in f.ChangedContents():
1363 if is_inside_javadoc and javadoc_end_re.search(line):
1364 is_inside_javadoc = False
1365 if not is_inside_javadoc and javadoc_start_re.search(line):
1366 is_inside_javadoc = True
1367 if is_inside_javadoc:
1368 continue
1369 if (inclusion_re.search(line) and
1370 not comment_re.search(line) and
1371 not exclusion_re.search(line)):
1372 problems.append(
1373 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1374
1375 if problems:
1376 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1377 else:
1378 return []
1379
1380
[email protected]10689ca2011-09-02 02:31:541381def _CheckNoIOStreamInHeaders(input_api, output_api):
1382 """Checks to make sure no .h files include <iostream>."""
1383 files = []
1384 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1385 input_api.re.MULTILINE)
1386 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1387 if not f.LocalPath().endswith('.h'):
1388 continue
1389 contents = input_api.ReadFile(f)
1390 if pattern.search(contents):
1391 files.append(f)
1392
1393 if len(files):
yolandyandaabc6d2016-04-18 18:29:391394 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061395 'Do not #include <iostream> in header files, since it inserts static '
1396 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541397 '#include <ostream>. See http://crbug.com/94794',
1398 files) ]
1399 return []
1400
Danil Chapovalov3518f362018-08-11 16:13:431401def _CheckNoStrCatRedefines(input_api, output_api):
1402 """Checks no windows headers with StrCat redefined are included directly."""
1403 files = []
1404 pattern_deny = input_api.re.compile(
1405 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1406 input_api.re.MULTILINE)
1407 pattern_allow = input_api.re.compile(
1408 r'^#include\s"base/win/windows_defines.inc"',
1409 input_api.re.MULTILINE)
1410 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1411 contents = input_api.ReadFile(f)
1412 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1413 files.append(f.LocalPath())
1414
1415 if len(files):
1416 return [output_api.PresubmitError(
1417 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1418 'directly since they pollute code with StrCat macro. Instead, '
1419 'include matching header from base/win. See http://crbug.com/856536',
1420 files) ]
1421 return []
1422
[email protected]10689ca2011-09-02 02:31:541423
[email protected]72df4e782012-06-21 16:28:181424def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521425 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181426 problems = []
1427 for f in input_api.AffectedFiles():
1428 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1429 continue
1430
1431 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041432 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181433 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1434
1435 if not problems:
1436 return []
1437 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1438 '\n'.join(problems))]
1439
Dominic Battre033531052018-09-24 15:45:341440def _CheckNoDISABLETypoInTests(input_api, output_api):
1441 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1442
1443 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1444 instead of DISABLED_. To filter false positives, reports are only generated
1445 if a corresponding MAYBE_ line exists.
1446 """
1447 problems = []
1448
1449 # The following two patterns are looked for in tandem - is a test labeled
1450 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1451 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1452 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1453
1454 # This is for the case that a test is disabled on all platforms.
1455 full_disable_pattern = input_api.re.compile(
1456 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1457 input_api.re.MULTILINE)
1458
Katie Df13948e2018-09-25 07:33:441459 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341460 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1461 continue
1462
1463 # Search for MABYE_, DISABLE_ pairs.
1464 disable_lines = {} # Maps of test name to line number.
1465 maybe_lines = {}
1466 for line_num, line in f.ChangedContents():
1467 disable_match = disable_pattern.search(line)
1468 if disable_match:
1469 disable_lines[disable_match.group(1)] = line_num
1470 maybe_match = maybe_pattern.search(line)
1471 if maybe_match:
1472 maybe_lines[maybe_match.group(1)] = line_num
1473
1474 # Search for DISABLE_ occurrences within a TEST() macro.
1475 disable_tests = set(disable_lines.keys())
1476 maybe_tests = set(maybe_lines.keys())
1477 for test in disable_tests.intersection(maybe_tests):
1478 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1479
1480 contents = input_api.ReadFile(f)
1481 full_disable_match = full_disable_pattern.search(contents)
1482 if full_disable_match:
1483 problems.append(' %s' % f.LocalPath())
1484
1485 if not problems:
1486 return []
1487 return [
1488 output_api.PresubmitPromptWarning(
1489 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1490 '\n'.join(problems))
1491 ]
1492
[email protected]72df4e782012-06-21 16:28:181493
danakj61c1aa22015-10-26 19:55:521494def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571495 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521496 errors = []
1497 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1498 input_api.re.MULTILINE)
1499 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1500 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1501 continue
1502 for lnum, line in f.ChangedContents():
1503 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171504 errors.append(output_api.PresubmitError(
1505 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571506 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171507 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521508 return errors
1509
1510
Makoto Shimazu3ad422cd2019-05-08 02:35:141511def _FindHistogramNameInChunk(histogram_name, chunk):
1512 """Tries to find a histogram name or prefix in a line.
1513
1514 Returns the existence of the histogram name, or None if it needs more chunk
1515 to determine."""
mcasasb7440c282015-02-04 14:52:191516 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1517 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141518 if '<affected-histogram' in chunk:
1519 # If the tag is not completed, needs more chunk to get the name.
1520 if not '>' in chunk:
1521 return None
1522 if not 'name="' in chunk:
1523 return False
1524 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1525 # expect the only attribute is the name.
1526 histogram_prefix = chunk.split('"')[1]
1527 return histogram_prefix in histogram_name
1528 # Typically the whole histogram name should in the line.
1529 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191530
1531
1532def _CheckUmaHistogramChanges(input_api, output_api):
1533 """Check that UMA histogram names in touched lines can still be found in other
1534 lines of the patch or in histograms.xml. Note that this check would not catch
1535 the reverse: changes in histograms.xml not matched in the code itself."""
1536 touched_histograms = []
1537 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471538 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1539 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1540 name_pattern = r'"(.*?)"'
1541 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1542 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1543 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1544 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1545 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171546 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191547 for f in input_api.AffectedFiles():
1548 # If histograms.xml itself is modified, keep the modified lines for later.
1549 if f.LocalPath().endswith(('histograms.xml')):
1550 histograms_xml_modifications = f.ChangedContents()
1551 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471552 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1553 single_line_re = single_line_c_re
1554 split_line_prefix_re = split_line_c_prefix_re
1555 elif f.LocalPath().endswith(('java')):
1556 single_line_re = single_line_java_re
1557 split_line_prefix_re = split_line_java_prefix_re
1558 else:
mcasasb7440c282015-02-04 14:52:191559 continue
1560 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171561 if last_line_matched_prefix:
1562 suffix_found = split_line_suffix_re.search(line)
1563 if suffix_found :
1564 touched_histograms.append([suffix_found.group(1), f, line_num])
1565 last_line_matched_prefix = False
1566 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061567 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191568 if found:
1569 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171570 continue
1571 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191572
1573 # Search for the touched histogram names in the local modifications to
1574 # histograms.xml, and, if not found, on the base histograms.xml file.
1575 unmatched_histograms = []
1576 for histogram_info in touched_histograms:
1577 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141578 chunk = ''
mcasasb7440c282015-02-04 14:52:191579 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141580 chunk += line
1581 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1582 if histogram_name_found is None:
1583 continue
1584 chunk = ''
mcasasb7440c282015-02-04 14:52:191585 if histogram_name_found:
1586 break
1587 if not histogram_name_found:
1588 unmatched_histograms.append(histogram_info)
1589
eromanb90c82e7e32015-04-01 15:13:491590 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191591 problems = []
1592 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491593 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191594 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451595 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191596 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141597 chunk = ''
mcasasb7440c282015-02-04 14:52:191598 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141599 chunk += line
1600 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1601 chunk)
1602 if histogram_name_found is None:
1603 continue
1604 chunk = ''
mcasasb7440c282015-02-04 14:52:191605 if histogram_name_found:
1606 break
1607 if not histogram_name_found:
1608 problems.append(' [%s:%d] %s' %
1609 (f.LocalPath(), line_num, histogram_name))
1610
1611 if not problems:
1612 return []
1613 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1614 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491615 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191616
wnwenbdc444e2016-05-25 13:44:151617
yolandyandaabc6d2016-04-18 18:29:391618def _CheckFlakyTestUsage(input_api, output_api):
1619 """Check that FlakyTest annotation is our own instead of the android one"""
1620 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1621 files = []
1622 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1623 if f.LocalPath().endswith('Test.java'):
1624 if pattern.search(input_api.ReadFile(f)):
1625 files.append(f)
1626 if len(files):
1627 return [output_api.PresubmitError(
1628 'Use org.chromium.base.test.util.FlakyTest instead of '
1629 'android.test.FlakyTest',
1630 files)]
1631 return []
mcasasb7440c282015-02-04 14:52:191632
wnwenbdc444e2016-05-25 13:44:151633
[email protected]8ea5d4b2011-09-13 21:49:221634def _CheckNoNewWStrings(input_api, output_api):
1635 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271636 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221637 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201638 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571639 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341640 '/win/' in f.LocalPath() or
1641 'chrome_elf' in f.LocalPath() or
1642 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201643 continue
[email protected]8ea5d4b2011-09-13 21:49:221644
[email protected]a11dbe9b2012-08-07 01:32:581645 allowWString = False
[email protected]b5c24292011-11-28 14:38:201646 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581647 if 'presubmit: allow wstring' in line:
1648 allowWString = True
1649 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271650 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581651 allowWString = False
1652 else:
1653 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221654
[email protected]55463aa62011-10-12 00:48:271655 if not problems:
1656 return []
1657 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581658 ' If you are calling a cross-platform API that accepts a wstring, '
1659 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271660 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221661
1662
[email protected]2a8ac9c2011-10-19 17:20:441663def _CheckNoDEPSGIT(input_api, output_api):
1664 """Make sure .DEPS.git is never modified manually."""
1665 if any(f.LocalPath().endswith('.DEPS.git') for f in
1666 input_api.AffectedFiles()):
1667 return [output_api.PresubmitError(
1668 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1669 'automated system based on what\'s in DEPS and your changes will be\n'
1670 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501671 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1672 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441673 'for more information')]
1674 return []
1675
1676
tandriief664692014-09-23 14:51:471677def _CheckValidHostsInDEPS(input_api, output_api):
1678 """Checks that DEPS file deps are from allowed_hosts."""
1679 # Run only if DEPS file has been modified to annoy fewer bystanders.
1680 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1681 return []
1682 # Outsource work to gclient verify
1683 try:
John Budorickf20c0042019-04-25 23:23:401684 gclient_path = input_api.os_path.join(
1685 input_api.PresubmitLocalPath(),
1686 'third_party', 'depot_tools', 'gclient.py')
1687 input_api.subprocess.check_output(
1688 [input_api.python_executable, gclient_path, 'verify'],
1689 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471690 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201691 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471692 return [output_api.PresubmitError(
1693 'DEPS file must have only git dependencies.',
1694 long_text=error.output)]
1695
1696
[email protected]127f18ec2012-06-16 05:05:591697def _CheckNoBannedFunctions(input_api, output_api):
1698 """Make sure that banned functions are not used."""
1699 warnings = []
1700 errors = []
1701
wnwenbdc444e2016-05-25 13:44:151702 def IsBlacklisted(affected_file, blacklist):
1703 local_path = affected_file.LocalPath()
1704 for item in blacklist:
1705 if input_api.re.match(item, local_path):
1706 return True
1707 return False
1708
Peter K. Lee6c03ccff2019-07-15 14:40:051709 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541710 local_path = affected_file.LocalPath()
1711 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1712 return False
1713 basename = input_api.os_path.basename(local_path)
1714 if 'ios' in basename.split('_'):
1715 return True
1716 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1717 if sep and 'ios' in local_path.split(sep):
1718 return True
1719 return False
1720
wnwenbdc444e2016-05-25 13:44:151721 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
1722 matched = False
1723 if func_name[0:1] == '/':
1724 regex = func_name[1:]
1725 if input_api.re.search(regex, line):
1726 matched = True
1727 elif func_name in line:
dchenge07de812016-06-20 19:27:171728 matched = True
wnwenbdc444e2016-05-25 13:44:151729 if matched:
dchenge07de812016-06-20 19:27:171730 problems = warnings
wnwenbdc444e2016-05-25 13:44:151731 if error:
dchenge07de812016-06-20 19:27:171732 problems = errors
wnwenbdc444e2016-05-25 13:44:151733 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
1734 for message_line in message:
1735 problems.append(' %s' % message_line)
1736
Eric Stevensona9a980972017-09-23 00:04:411737 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1738 for f in input_api.AffectedFiles(file_filter=file_filter):
1739 for line_num, line in f.ChangedContents():
1740 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1741 CheckForMatch(f, line_num, line, func_name, message, error)
1742
[email protected]127f18ec2012-06-16 05:05:591743 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1744 for f in input_api.AffectedFiles(file_filter=file_filter):
1745 for line_num, line in f.ChangedContents():
1746 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151747 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591748
Peter K. Lee6c03ccff2019-07-15 14:40:051749 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541750 for line_num, line in f.ChangedContents():
1751 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1752 CheckForMatch(f, line_num, line, func_name, message, error)
1753
Peter K. Lee6c03ccff2019-07-15 14:40:051754 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1755 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1756 for line_num, line in f.ChangedContents():
1757 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1758 CheckForMatch(f, line_num, line, func_name, message, error)
1759
[email protected]127f18ec2012-06-16 05:05:591760 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1761 for f in input_api.AffectedFiles(file_filter=file_filter):
1762 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491763 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491764 if IsBlacklisted(f, excluded_paths):
1765 continue
wnwenbdc444e2016-05-25 13:44:151766 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591767
1768 result = []
1769 if (warnings):
1770 result.append(output_api.PresubmitPromptWarning(
1771 'Banned functions were used.\n' + '\n'.join(warnings)))
1772 if (errors):
1773 result.append(output_api.PresubmitError(
1774 'Banned functions were used.\n' + '\n'.join(errors)))
1775 return result
1776
1777
[email protected]6c063c62012-07-11 19:11:061778def _CheckNoPragmaOnce(input_api, output_api):
1779 """Make sure that banned functions are not used."""
1780 files = []
1781 pattern = input_api.re.compile(r'^#pragma\s+once',
1782 input_api.re.MULTILINE)
1783 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1784 if not f.LocalPath().endswith('.h'):
1785 continue
1786 contents = input_api.ReadFile(f)
1787 if pattern.search(contents):
1788 files.append(f)
1789
1790 if files:
1791 return [output_api.PresubmitError(
1792 'Do not use #pragma once in header files.\n'
1793 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1794 files)]
1795 return []
1796
[email protected]127f18ec2012-06-16 05:05:591797
[email protected]e7479052012-09-19 00:26:121798def _CheckNoTrinaryTrueFalse(input_api, output_api):
1799 """Checks to make sure we don't introduce use of foo ? true : false."""
1800 problems = []
1801 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1802 for f in input_api.AffectedFiles():
1803 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1804 continue
1805
1806 for line_num, line in f.ChangedContents():
1807 if pattern.match(line):
1808 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1809
1810 if not problems:
1811 return []
1812 return [output_api.PresubmitPromptWarning(
1813 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1814 '\n'.join(problems))]
1815
1816
[email protected]55f9f382012-07-31 11:02:181817def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281818 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181819 change. Breaking - rules is an error, breaking ! rules is a
1820 warning.
1821 """
mohan.reddyf21db962014-10-16 12:26:471822 import sys
[email protected]55f9f382012-07-31 11:02:181823 # We need to wait until we have an input_api object and use this
1824 # roundabout construct to import checkdeps because this file is
1825 # eval-ed and thus doesn't have __file__.
1826 original_sys_path = sys.path
1827 try:
1828 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471829 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181830 import checkdeps
[email protected]55f9f382012-07-31 11:02:181831 from rules import Rule
1832 finally:
1833 # Restore sys.path to what it was before.
1834 sys.path = original_sys_path
1835
1836 added_includes = []
rhalavati08acd232017-04-03 07:23:281837 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241838 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181839 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:061840 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501841 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081842 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061843 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501844 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081845 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061846 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501847 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081848 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181849
[email protected]26385172013-05-09 23:11:351850 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181851
1852 error_descriptions = []
1853 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281854 error_subjects = set()
1855 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181856 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1857 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081858 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181859 description_with_path = '%s\n %s' % (path, rule_description)
1860 if rule_type == Rule.DISALLOW:
1861 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281862 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181863 else:
1864 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281865 warning_subjects.add("#includes")
1866
1867 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1868 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081869 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281870 description_with_path = '%s\n %s' % (path, rule_description)
1871 if rule_type == Rule.DISALLOW:
1872 error_descriptions.append(description_with_path)
1873 error_subjects.add("imports")
1874 else:
1875 warning_descriptions.append(description_with_path)
1876 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181877
Jinsuk Kim5a092672017-10-24 22:42:241878 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021879 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081880 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241881 description_with_path = '%s\n %s' % (path, rule_description)
1882 if rule_type == Rule.DISALLOW:
1883 error_descriptions.append(description_with_path)
1884 error_subjects.add("imports")
1885 else:
1886 warning_descriptions.append(description_with_path)
1887 warning_subjects.add("imports")
1888
[email protected]55f9f382012-07-31 11:02:181889 results = []
1890 if error_descriptions:
1891 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281892 'You added one or more %s that violate checkdeps rules.'
1893 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181894 error_descriptions))
1895 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421896 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281897 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181898 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281899 '%s? See relevant DEPS file(s) for details and contacts.' %
1900 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181901 warning_descriptions))
1902 return results
1903
1904
[email protected]fbcafe5a2012-08-08 15:31:221905def _CheckFilePermissions(input_api, output_api):
1906 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151907 if input_api.platform == 'win32':
1908 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291909 checkperms_tool = input_api.os_path.join(
1910 input_api.PresubmitLocalPath(),
1911 'tools', 'checkperms', 'checkperms.py')
1912 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471913 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391914 with input_api.CreateTemporaryFile() as file_list:
1915 for f in input_api.AffectedFiles():
1916 # checkperms.py file/directory arguments must be relative to the
1917 # repository.
1918 file_list.write(f.LocalPath() + '\n')
1919 file_list.close()
1920 args += ['--file-list', file_list.name]
1921 try:
1922 input_api.subprocess.check_output(args)
1923 return []
1924 except input_api.subprocess.CalledProcessError as error:
1925 return [output_api.PresubmitError(
1926 'checkperms.py failed:',
1927 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221928
1929
robertocn832f5992017-01-04 19:01:301930def _CheckTeamTags(input_api, output_api):
1931 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1932 checkteamtags_tool = input_api.os_path.join(
1933 input_api.PresubmitLocalPath(),
1934 'tools', 'checkteamtags', 'checkteamtags.py')
1935 args = [input_api.python_executable, checkteamtags_tool,
1936 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221937 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301938 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1939 'OWNERS']
1940 try:
1941 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:051942 warnings = input_api.subprocess.check_output(args + files).splitlines()
1943 if warnings:
1944 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:301945 return []
1946 except input_api.subprocess.CalledProcessError as error:
1947 return [output_api.PresubmitError(
1948 'checkteamtags.py failed:',
1949 long_text=error.output)]
1950
1951
[email protected]c8278b32012-10-30 20:35:491952def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1953 """Makes sure we don't include ui/aura/window_property.h
1954 in header files.
1955 """
1956 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1957 errors = []
1958 for f in input_api.AffectedFiles():
1959 if not f.LocalPath().endswith('.h'):
1960 continue
1961 for line_num, line in f.ChangedContents():
1962 if pattern.match(line):
1963 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1964
1965 results = []
1966 if errors:
1967 results.append(output_api.PresubmitError(
1968 'Header files should not include ui/aura/window_property.h', errors))
1969 return results
1970
1971
[email protected]70ca77752012-11-20 03:45:031972def _CheckForVersionControlConflictsInFile(input_api, f):
1973 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1974 errors = []
1975 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:161976 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:231977 # First-level headers in markdown look a lot like version control
1978 # conflict markers. http://daringfireball.net/projects/markdown/basics
1979 continue
[email protected]70ca77752012-11-20 03:45:031980 if pattern.match(line):
1981 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1982 return errors
1983
1984
1985def _CheckForVersionControlConflicts(input_api, output_api):
1986 """Usually this is not intentional and will cause a compile failure."""
1987 errors = []
1988 for f in input_api.AffectedFiles():
1989 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1990
1991 results = []
1992 if errors:
1993 results.append(output_api.PresubmitError(
1994 'Version control conflict markers found, please resolve.', errors))
1995 return results
1996
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201997
estadee17314a02017-01-12 16:22:161998def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1999 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2000 errors = []
2001 for f in input_api.AffectedFiles():
2002 for line_num, line in f.ChangedContents():
2003 if pattern.search(line):
2004 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2005
2006 results = []
2007 if errors:
2008 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502009 'Found Google support URL addressed by answer number. Please replace '
2010 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162011 return results
2012
[email protected]70ca77752012-11-20 03:45:032013
[email protected]06e6d0ff2012-12-11 01:36:442014def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2015 def FilterFile(affected_file):
2016 """Filter function for use with input_api.AffectedSourceFiles,
2017 below. This filters out everything except non-test files from
2018 top-level directories that generally speaking should not hard-code
2019 service URLs (e.g. src/android_webview/, src/content/ and others).
2020 """
2021 return input_api.FilterSourceFile(
2022 affected_file,
Egor Paskoce145c42018-09-28 19:31:042023 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442024 black_list=(_EXCLUDED_PATHS +
2025 _TEST_CODE_EXCLUDED_PATHS +
2026 input_api.DEFAULT_BLACK_LIST))
2027
reillyi38965732015-11-16 18:27:332028 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2029 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462030 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2031 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442032 problems = [] # items are (filename, line_number, line)
2033 for f in input_api.AffectedSourceFiles(FilterFile):
2034 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462035 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442036 problems.append((f.LocalPath(), line_num, line))
2037
2038 if problems:
[email protected]f7051d52013-04-02 18:31:422039 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442040 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582041 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442042 [' %s:%d: %s' % (
2043 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032044 else:
2045 return []
[email protected]06e6d0ff2012-12-11 01:36:442046
2047
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492048# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272049def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2050 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312051 The native_client_sdk directory is excluded because it has auto-generated PNG
2052 files for documentation.
[email protected]d2530012013-01-25 16:39:272053 """
[email protected]d2530012013-01-25 16:39:272054 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492055 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042056 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312057 file_filter = lambda f: input_api.FilterSourceFile(
2058 f, white_list=white_list, black_list=black_list)
2059 for f in input_api.AffectedFiles(include_deletes=False,
2060 file_filter=file_filter):
2061 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272062
2063 results = []
2064 if errors:
2065 results.append(output_api.PresubmitError(
2066 'The name of PNG files should not have abbreviations. \n'
2067 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2068 'Contact [email protected] if you have questions.', errors))
2069 return results
2070
2071
Daniel Cheng4dcdb6b2017-04-13 08:30:172072def _ExtractAddRulesFromParsedDeps(parsed_deps):
2073 """Extract the rules that add dependencies from a parsed DEPS file.
2074
2075 Args:
2076 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2077 add_rules = set()
2078 add_rules.update([
2079 rule[1:] for rule in parsed_deps.get('include_rules', [])
2080 if rule.startswith('+') or rule.startswith('!')
2081 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502082 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172083 {}).iteritems():
2084 add_rules.update([
2085 rule[1:] for rule in rules
2086 if rule.startswith('+') or rule.startswith('!')
2087 ])
2088 return add_rules
2089
2090
2091def _ParseDeps(contents):
2092 """Simple helper for parsing DEPS files."""
2093 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172094 class _VarImpl:
2095
2096 def __init__(self, local_scope):
2097 self._local_scope = local_scope
2098
2099 def Lookup(self, var_name):
2100 """Implements the Var syntax."""
2101 try:
2102 return self._local_scope['vars'][var_name]
2103 except KeyError:
2104 raise Exception('Var is not defined: %s' % var_name)
2105
2106 local_scope = {}
2107 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172108 'Var': _VarImpl(local_scope).Lookup,
2109 }
2110 exec contents in global_scope, local_scope
2111 return local_scope
2112
2113
2114def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082115 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412116 a set of DEPS entries that we should look up.
2117
2118 For a directory (rather than a specific filename) we fake a path to
2119 a specific filename by adding /DEPS. This is chosen as a file that
2120 will seldom or never be subject to per-file include_rules.
2121 """
[email protected]2b438d62013-11-14 17:54:142122 # We ignore deps entries on auto-generated directories.
2123 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082124
Daniel Cheng4dcdb6b2017-04-13 08:30:172125 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2126 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2127
2128 added_deps = new_deps.difference(old_deps)
2129
[email protected]2b438d62013-11-14 17:54:142130 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172131 for added_dep in added_deps:
2132 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2133 continue
2134 # Assume that a rule that ends in .h is a rule for a specific file.
2135 if added_dep.endswith('.h'):
2136 results.add(added_dep)
2137 else:
2138 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082139 return results
2140
2141
[email protected]e871964c2013-05-13 14:14:552142def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2143 """When a dependency prefixed with + is added to a DEPS file, we
2144 want to make sure that the change is reviewed by an OWNER of the
2145 target file or directory, to avoid layering violations from being
2146 introduced. This check verifies that this happens.
2147 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172148 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242149
2150 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492151 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242152 for f in input_api.AffectedFiles(include_deletes=False,
2153 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552154 filename = input_api.os_path.basename(f.LocalPath())
2155 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172156 virtual_depended_on_files.update(_CalculateAddedDeps(
2157 input_api.os_path,
2158 '\n'.join(f.OldContents()),
2159 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552160
[email protected]e871964c2013-05-13 14:14:552161 if not virtual_depended_on_files:
2162 return []
2163
2164 if input_api.is_committing:
2165 if input_api.tbr:
2166 return [output_api.PresubmitNotifyResult(
2167 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272168 if input_api.dry_run:
2169 return [output_api.PresubmitNotifyResult(
2170 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552171 if not input_api.change.issue:
2172 return [output_api.PresubmitError(
2173 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402174 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552175 output = output_api.PresubmitError
2176 else:
2177 output = output_api.PresubmitNotifyResult
2178
2179 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502180 owner_email, reviewers = (
2181 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2182 input_api,
2183 owners_db.email_regexp,
2184 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552185
2186 owner_email = owner_email or input_api.change.author_email
2187
[email protected]de4f7d22013-05-23 14:27:462188 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512189 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462190 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552191 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2192 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412193
2194 # We strip the /DEPS part that was added by
2195 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2196 # directory.
2197 def StripDeps(path):
2198 start_deps = path.rfind('/DEPS')
2199 if start_deps != -1:
2200 return path[:start_deps]
2201 else:
2202 return path
2203 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552204 for path in missing_files]
2205
2206 if unapproved_dependencies:
2207 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152208 output('You need LGTM from owners of depends-on paths in DEPS that were '
2209 'modified in this CL:\n %s' %
2210 '\n '.join(sorted(unapproved_dependencies)))]
2211 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2212 output_list.append(output(
2213 'Suggested missing target path OWNERS:\n %s' %
2214 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552215 return output_list
2216
2217 return []
2218
2219
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492220# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402221def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492222 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402223 black_list = (_EXCLUDED_PATHS +
2224 _TEST_CODE_EXCLUDED_PATHS +
2225 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042226 (r"^base[\\/]logging\.h$",
2227 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222228 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042229 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2230 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2231 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122232 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182233 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152234 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032235 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152236 r"^chrome[\\/]chrome_cleaner[\\/].*",
2237 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2238 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042239 r"^chromecast[\\/]",
2240 r"^cloud_print[\\/]",
2241 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482242 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042243 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312244 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042245 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462246 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042247 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462248 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042249 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252250 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042251 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2252 r"^courgette[\\/]courgette_tool\.cc$",
2253 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272254 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332255 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042256 r"^ipc[\\/]ipc_logging\.cc$",
2257 r"^native_client_sdk[\\/]",
2258 r"^remoting[\\/]base[\\/]logging\.h$",
2259 r"^remoting[\\/]host[\\/].*",
2260 r"^sandbox[\\/]linux[\\/].*",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332261 r"^storage[\\/]browser[\\/]fileapi[\\/]" +
2262 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042263 r"^tools[\\/]",
2264 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2265 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332266 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402267 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492268 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402269
thomasanderson625d3932017-03-29 07:16:582270 log_info = set([])
2271 printf = set([])
[email protected]85218562013-11-22 07:41:402272
2273 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582274 for _, line in f.ChangedContents():
2275 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2276 log_info.add(f.LocalPath())
2277 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2278 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372279
thomasanderson625d3932017-03-29 07:16:582280 if input_api.re.search(r"\bprintf\(", line):
2281 printf.add(f.LocalPath())
2282 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2283 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402284
2285 if log_info:
2286 return [output_api.PresubmitError(
2287 'These files spam the console log with LOG(INFO):',
2288 items=log_info)]
2289 if printf:
2290 return [output_api.PresubmitError(
2291 'These files spam the console log with printf/fprintf:',
2292 items=printf)]
2293 return []
2294
2295
[email protected]49aa76a2013-12-04 06:59:162296def _CheckForAnonymousVariables(input_api, output_api):
2297 """These types are all expected to hold locks while in scope and
2298 so should never be anonymous (which causes them to be immediately
2299 destroyed)."""
2300 they_who_must_be_named = [
2301 'base::AutoLock',
2302 'base::AutoReset',
2303 'base::AutoUnlock',
2304 'SkAutoAlphaRestore',
2305 'SkAutoBitmapShaderInstall',
2306 'SkAutoBlitterChoose',
2307 'SkAutoBounderCommit',
2308 'SkAutoCallProc',
2309 'SkAutoCanvasRestore',
2310 'SkAutoCommentBlock',
2311 'SkAutoDescriptor',
2312 'SkAutoDisableDirectionCheck',
2313 'SkAutoDisableOvalCheck',
2314 'SkAutoFree',
2315 'SkAutoGlyphCache',
2316 'SkAutoHDC',
2317 'SkAutoLockColors',
2318 'SkAutoLockPixels',
2319 'SkAutoMalloc',
2320 'SkAutoMaskFreeImage',
2321 'SkAutoMutexAcquire',
2322 'SkAutoPathBoundsUpdate',
2323 'SkAutoPDFRelease',
2324 'SkAutoRasterClipValidate',
2325 'SkAutoRef',
2326 'SkAutoTime',
2327 'SkAutoTrace',
2328 'SkAutoUnref',
2329 ]
2330 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2331 # bad: base::AutoLock(lock.get());
2332 # not bad: base::AutoLock lock(lock.get());
2333 bad_pattern = input_api.re.compile(anonymous)
2334 # good: new base::AutoLock(lock.get())
2335 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2336 errors = []
2337
2338 for f in input_api.AffectedFiles():
2339 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2340 continue
2341 for linenum, line in f.ChangedContents():
2342 if bad_pattern.search(line) and not good_pattern.search(line):
2343 errors.append('%s:%d' % (f.LocalPath(), linenum))
2344
2345 if errors:
2346 return [output_api.PresubmitError(
2347 'These lines create anonymous variables that need to be named:',
2348 items=errors)]
2349 return []
2350
2351
Peter Kasting4844e46e2018-02-23 07:27:102352def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532353 # Returns whether |template_str| is of the form <T, U...> for some types T
2354 # and U. Assumes that |template_str| is already in the form <...>.
2355 def HasMoreThanOneArg(template_str):
2356 # Level of <...> nesting.
2357 nesting = 0
2358 for c in template_str:
2359 if c == '<':
2360 nesting += 1
2361 elif c == '>':
2362 nesting -= 1
2363 elif c == ',' and nesting == 1:
2364 return True
2365 return False
2366
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492367 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102368 sources = lambda affected_file: input_api.FilterSourceFile(
2369 affected_file,
2370 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2371 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492372 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552373
2374 # Pattern to capture a single "<...>" block of template arguments. It can
2375 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2376 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2377 # latter would likely require counting that < and > match, which is not
2378 # expressible in regular languages. Should the need arise, one can introduce
2379 # limited counting (matching up to a total number of nesting depth), which
2380 # should cover all practical cases for already a low nesting limit.
2381 template_arg_pattern = (
2382 r'<[^>]*' # Opening block of <.
2383 r'>([^<]*>)?') # Closing block of >.
2384 # Prefix expressing that whatever follows is not already inside a <...>
2385 # block.
2386 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102387 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552388 not_inside_template_arg_pattern
2389 + r'\bstd::unique_ptr'
2390 + template_arg_pattern
2391 + r'\(\)')
2392
2393 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2394 template_arg_no_array_pattern = (
2395 r'<[^>]*[^]]' # Opening block of <.
2396 r'>([^(<]*[^]]>)?') # Closing block of >.
2397 # Prefix saying that what follows is the start of an expression.
2398 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2399 # Suffix saying that what follows are call parentheses with a non-empty list
2400 # of arguments.
2401 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532402 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552403 return_construct_pattern = input_api.re.compile(
2404 start_of_expr_pattern
2405 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532406 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552407 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532408 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552409 + nonempty_arg_list_pattern)
2410
Vaclav Brozek851d9602018-04-04 16:13:052411 problems_constructor = []
2412 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102413 for f in input_api.AffectedSourceFiles(sources):
2414 for line_number, line in f.ChangedContents():
2415 # Disallow:
2416 # return std::unique_ptr<T>(foo);
2417 # bar = std::unique_ptr<T>(foo);
2418 # But allow:
2419 # return std::unique_ptr<T[]>(foo);
2420 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532421 # And also allow cases when the second template argument is present. Those
2422 # cases cannot be handled by std::make_unique:
2423 # return std::unique_ptr<T, U>(foo);
2424 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052425 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532426 return_construct_result = return_construct_pattern.search(line)
2427 if return_construct_result and not HasMoreThanOneArg(
2428 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052429 problems_constructor.append(
2430 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102431 # Disallow:
2432 # std::unique_ptr<T>()
2433 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052434 problems_nullptr.append(
2435 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2436
2437 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162438 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052439 errors.append(output_api.PresubmitError(
2440 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162441 problems_nullptr))
2442 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052443 errors.append(output_api.PresubmitError(
2444 'The following files use explicit std::unique_ptr constructor.'
2445 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162446 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102447 return errors
2448
2449
[email protected]999261d2014-03-03 20:08:082450def _CheckUserActionUpdate(input_api, output_api):
2451 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522452 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082453 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522454 # If actions.xml is already included in the changelist, the PRESUBMIT
2455 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082456 return []
2457
[email protected]999261d2014-03-03 20:08:082458 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2459 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522460 current_actions = None
[email protected]999261d2014-03-03 20:08:082461 for f in input_api.AffectedFiles(file_filter=file_filter):
2462 for line_num, line in f.ChangedContents():
2463 match = input_api.re.search(action_re, line)
2464 if match:
[email protected]2f92dec2014-03-07 19:21:522465 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2466 # loaded only once.
2467 if not current_actions:
2468 with open('tools/metrics/actions/actions.xml') as actions_f:
2469 current_actions = actions_f.read()
2470 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082471 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522472 action = 'name="{0}"'.format(action_name)
2473 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082474 return [output_api.PresubmitPromptWarning(
2475 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522476 'tools/metrics/actions/actions.xml. Please run '
2477 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082478 % (f.LocalPath(), line_num, action_name))]
2479 return []
2480
2481
Daniel Cheng13ca61a882017-08-25 15:11:252482def _ImportJSONCommentEater(input_api):
2483 import sys
2484 sys.path = sys.path + [input_api.os_path.join(
2485 input_api.PresubmitLocalPath(),
2486 'tools', 'json_comment_eater')]
2487 import json_comment_eater
2488 return json_comment_eater
2489
2490
[email protected]99171a92014-06-03 08:44:472491def _GetJSONParseError(input_api, filename, eat_comments=True):
2492 try:
2493 contents = input_api.ReadFile(filename)
2494 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252495 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132496 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472497
2498 input_api.json.loads(contents)
2499 except ValueError as e:
2500 return e
2501 return None
2502
2503
2504def _GetIDLParseError(input_api, filename):
2505 try:
2506 contents = input_api.ReadFile(filename)
2507 idl_schema = input_api.os_path.join(
2508 input_api.PresubmitLocalPath(),
2509 'tools', 'json_schema_compiler', 'idl_schema.py')
2510 process = input_api.subprocess.Popen(
2511 [input_api.python_executable, idl_schema],
2512 stdin=input_api.subprocess.PIPE,
2513 stdout=input_api.subprocess.PIPE,
2514 stderr=input_api.subprocess.PIPE,
2515 universal_newlines=True)
2516 (_, error) = process.communicate(input=contents)
2517 return error or None
2518 except ValueError as e:
2519 return e
2520
2521
2522def _CheckParseErrors(input_api, output_api):
2523 """Check that IDL and JSON files do not contain syntax errors."""
2524 actions = {
2525 '.idl': _GetIDLParseError,
2526 '.json': _GetJSONParseError,
2527 }
[email protected]99171a92014-06-03 08:44:472528 # Most JSON files are preprocessed and support comments, but these do not.
2529 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042530 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472531 ]
2532 # Only run IDL checker on files in these directories.
2533 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042534 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2535 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472536 ]
2537
2538 def get_action(affected_file):
2539 filename = affected_file.LocalPath()
2540 return actions.get(input_api.os_path.splitext(filename)[1])
2541
[email protected]99171a92014-06-03 08:44:472542 def FilterFile(affected_file):
2543 action = get_action(affected_file)
2544 if not action:
2545 return False
2546 path = affected_file.LocalPath()
2547
Sean Kau46e29bc2017-08-28 16:31:162548 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472549 return False
2550
2551 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162552 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472553 return False
2554 return True
2555
2556 results = []
2557 for affected_file in input_api.AffectedFiles(
2558 file_filter=FilterFile, include_deletes=False):
2559 action = get_action(affected_file)
2560 kwargs = {}
2561 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162562 _MatchesFile(input_api, json_no_comments_patterns,
2563 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472564 kwargs['eat_comments'] = False
2565 parse_error = action(input_api,
2566 affected_file.AbsoluteLocalPath(),
2567 **kwargs)
2568 if parse_error:
2569 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2570 (affected_file.LocalPath(), parse_error)))
2571 return results
2572
2573
[email protected]760deea2013-12-10 19:33:492574def _CheckJavaStyle(input_api, output_api):
2575 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472576 import sys
[email protected]760deea2013-12-10 19:33:492577 original_sys_path = sys.path
2578 try:
2579 sys.path = sys.path + [input_api.os_path.join(
2580 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2581 import checkstyle
2582 finally:
2583 # Restore sys.path to what it was before.
2584 sys.path = original_sys_path
2585
2586 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092587 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512588 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492589
2590
Nate Fischerdfd9812e2019-07-18 22:03:002591def _CheckPythonDevilInit(input_api, output_api):
2592 """Checks to make sure devil is initialized correctly in python scripts."""
2593 script_common_initialize_pattern = input_api.re.compile(
2594 r'script_common\.InitializeEnvironment\(')
2595 devil_env_config_initialize = input_api.re.compile(
2596 r'devil_env\.config\.Initialize\(')
2597
2598 errors = []
2599
2600 sources = lambda affected_file: input_api.FilterSourceFile(
2601 affected_file,
2602 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2603 (r'^build[\\/]android[\\/]devil_chromium\.py',
2604 r'^third_party[\\/].*',)),
2605 white_list=[r'.*\.py$'])
2606
2607 for f in input_api.AffectedSourceFiles(sources):
2608 for line_num, line in f.ChangedContents():
2609 if (script_common_initialize_pattern.search(line) or
2610 devil_env_config_initialize.search(line)):
2611 errors.append("%s:%d" % (f.LocalPath(), line_num))
2612
2613 results = []
2614
2615 if errors:
2616 results.append(output_api.PresubmitError(
2617 'Devil initialization should always be done using '
2618 'devil_chromium.Initialize() in the chromium project, to use better '
2619 'defaults for dependencies (ex. up-to-date version of adb).',
2620 errors))
2621
2622 return results
2623
2624
Sean Kau46e29bc2017-08-28 16:31:162625def _MatchesFile(input_api, patterns, path):
2626 for pattern in patterns:
2627 if input_api.re.search(pattern, path):
2628 return True
2629 return False
2630
2631
Daniel Cheng7052cdf2017-11-21 19:23:292632def _GetOwnersFilesToCheckForIpcOwners(input_api):
2633 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172634
Daniel Cheng7052cdf2017-11-21 19:23:292635 Returns:
2636 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2637 contain to cover IPC-related files with noparent reviewer rules.
2638 """
2639 # Whether or not a file affects IPC is (mostly) determined by a simple list
2640 # of filename patterns.
dchenge07de812016-06-20 19:27:172641 file_patterns = [
palmerb19a0932017-01-24 04:00:312642 # Legacy IPC:
dchenge07de812016-06-20 19:27:172643 '*_messages.cc',
2644 '*_messages*.h',
2645 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312646 # Mojo IPC:
dchenge07de812016-06-20 19:27:172647 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472648 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172649 '*_struct_traits*.*',
2650 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312651 '*.typemap',
2652 # Android native IPC:
2653 '*.aidl',
2654 # Blink uses a different file naming convention:
2655 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472656 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172657 '*StructTraits*.*',
2658 '*TypeConverter*.*',
2659 ]
2660
scottmg7a6ed5ba2016-11-04 18:22:042661 # These third_party directories do not contain IPCs, but contain files
2662 # matching the above patterns, which trigger false positives.
2663 exclude_paths = [
2664 'third_party/crashpad/*',
Andres Medinae684cf42018-08-27 18:48:232665 'third_party/protobuf/benchmarks/python/*',
Daniel Chengebe635e2018-07-13 12:36:062666 'third_party/third_party/blink/renderer/platform/bindings/*',
Nico Weberee3dc9b2017-08-31 17:09:292667 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:042668 ]
2669
dchenge07de812016-06-20 19:27:172670 # Dictionary mapping an OWNERS file path to Patterns.
2671 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2672 # rules ) to a PatternEntry.
2673 # PatternEntry is a dictionary with two keys:
2674 # - 'files': the files that are matched by this pattern
2675 # - 'rules': the per-file rules needed for this pattern
2676 # For example, if we expect OWNERS file to contain rules for *.mojom and
2677 # *_struct_traits*.*, Patterns might look like this:
2678 # {
2679 # '*.mojom': {
2680 # 'files': ...,
2681 # 'rules': [
2682 # 'per-file *.mojom=set noparent',
2683 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2684 # ],
2685 # },
2686 # '*_struct_traits*.*': {
2687 # 'files': ...,
2688 # 'rules': [
2689 # 'per-file *_struct_traits*.*=set noparent',
2690 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2691 # ],
2692 # },
2693 # }
2694 to_check = {}
2695
Daniel Cheng13ca61a882017-08-25 15:11:252696 def AddPatternToCheck(input_file, pattern):
2697 owners_file = input_api.os_path.join(
2698 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2699 if owners_file not in to_check:
2700 to_check[owners_file] = {}
2701 if pattern not in to_check[owners_file]:
2702 to_check[owners_file][pattern] = {
2703 'files': [],
2704 'rules': [
2705 'per-file %s=set noparent' % pattern,
2706 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2707 ]
2708 }
Vaclav Brozekd5de76a2018-03-17 07:57:502709 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252710
dchenge07de812016-06-20 19:27:172711 # Iterate through the affected files to see what we actually need to check
2712 # for. We should only nag patch authors about per-file rules if a file in that
2713 # directory would match that pattern. If a directory only contains *.mojom
2714 # files and no *_messages*.h files, we should only nag about rules for
2715 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252716 for f in input_api.AffectedFiles(include_deletes=False):
2717 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362718 # affected files for .json, .cc, and .h files which look like they contain
2719 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162720 if (f.LocalPath().endswith('.json') and
2721 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2722 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252723 json_comment_eater = _ImportJSONCommentEater(input_api)
2724 mostly_json_lines = '\n'.join(f.NewContents())
2725 # Comments aren't allowed in strict JSON, so filter them out.
2726 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432727 try:
2728 json_content = input_api.json.loads(json_lines)
2729 except:
2730 # There's another PRESUBMIT check that already verifies that JSON files
2731 # are not invalid, so no need to emit another warning here.
2732 continue
Daniel Cheng13ca61a882017-08-25 15:11:252733 if 'interface_provider_specs' in json_content:
2734 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362735 else:
2736 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2737 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2738 if (manifest_pattern.search(f.LocalPath()) and not
2739 test_manifest_pattern.search(f.LocalPath())):
2740 # We expect all actual service manifest files to contain at least one
2741 # qualified reference to service_manager::Manifest.
2742 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2743 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172744 for pattern in file_patterns:
2745 if input_api.fnmatch.fnmatch(
2746 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042747 skip = False
2748 for exclude in exclude_paths:
2749 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2750 skip = True
2751 break
2752 if skip:
2753 continue
Daniel Cheng13ca61a882017-08-25 15:11:252754 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172755 break
2756
Daniel Cheng7052cdf2017-11-21 19:23:292757 return to_check
2758
2759
2760def _CheckIpcOwners(input_api, output_api):
2761 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2762 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2763
2764 if to_check:
2765 # If there are any OWNERS files to check, there are IPC-related changes in
2766 # this CL. Auto-CC the review list.
2767 output_api.AppendCC('[email protected]')
2768
2769 # Go through the OWNERS files to check, filtering out rules that are already
2770 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172771 for owners_file, patterns in to_check.iteritems():
2772 try:
2773 with file(owners_file) as f:
2774 lines = set(f.read().splitlines())
2775 for entry in patterns.itervalues():
2776 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2777 ]
2778 except IOError:
2779 # No OWNERS file, so all the rules are definitely missing.
2780 continue
2781
2782 # All the remaining lines weren't found in OWNERS files, so emit an error.
2783 errors = []
2784 for owners_file, patterns in to_check.iteritems():
2785 missing_lines = []
2786 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502787 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172788 missing_lines.extend(entry['rules'])
2789 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2790 if missing_lines:
2791 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:052792 'Because of the presence of files:\n%s\n\n'
2793 '%s needs the following %d lines added:\n\n%s' %
2794 ('\n'.join(files), owners_file, len(missing_lines),
2795 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:172796
2797 results = []
2798 if errors:
vabrf5ce3bf92016-07-11 14:52:412799 if input_api.is_committing:
2800 output = output_api.PresubmitError
2801 else:
2802 output = output_api.PresubmitPromptWarning
2803 results.append(output(
Daniel Cheng52111692017-06-14 08:00:592804 'Found OWNERS files that need to be updated for IPC security ' +
2805 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:172806 long_text='\n\n'.join(errors)))
2807
2808 return results
2809
2810
jbriance9e12f162016-11-25 07:57:502811def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:312812 """Checks that added or removed lines in non third party affected
2813 header files do not lead to new useless class or struct forward
2814 declaration.
jbriance9e12f162016-11-25 07:57:502815 """
2816 results = []
2817 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
2818 input_api.re.MULTILINE)
2819 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
2820 input_api.re.MULTILINE)
2821 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:312822 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:192823 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:492824 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:312825 continue
2826
jbriance9e12f162016-11-25 07:57:502827 if not f.LocalPath().endswith('.h'):
2828 continue
2829
2830 contents = input_api.ReadFile(f)
2831 fwd_decls = input_api.re.findall(class_pattern, contents)
2832 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
2833
2834 useless_fwd_decls = []
2835 for decl in fwd_decls:
2836 count = sum(1 for _ in input_api.re.finditer(
2837 r'\b%s\b' % input_api.re.escape(decl), contents))
2838 if count == 1:
2839 useless_fwd_decls.append(decl)
2840
2841 if not useless_fwd_decls:
2842 continue
2843
2844 for line in f.GenerateScmDiff().splitlines():
2845 if (line.startswith('-') and not line.startswith('--') or
2846 line.startswith('+') and not line.startswith('++')):
2847 for decl in useless_fwd_decls:
2848 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2849 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242850 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502851 (f.LocalPath(), decl)))
2852 useless_fwd_decls.remove(decl)
2853
2854 return results
2855
Jinsong Fan91ebbbd2019-04-16 14:57:172856def _CheckAndroidDebuggableBuild(input_api, output_api):
2857 """Checks that code uses BuildInfo.isDebugAndroid() instead of
2858 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
2859 this is a debuggable build of Android.
2860 """
2861 build_type_check_pattern = input_api.re.compile(
2862 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
2863
2864 errors = []
2865
2866 sources = lambda affected_file: input_api.FilterSourceFile(
2867 affected_file,
2868 black_list=(_EXCLUDED_PATHS +
2869 _TEST_CODE_EXCLUDED_PATHS +
2870 input_api.DEFAULT_BLACK_LIST +
2871 (r"^android_webview[\\/]support_library[\\/]"
2872 "boundary_interfaces[\\/]",
2873 r"^chrome[\\/]android[\\/]webapk[\\/].*",
2874 r'^third_party[\\/].*',
2875 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
2876 r"webview[\\/]chromium[\\/]License.*",)),
2877 white_list=[r'.*\.java$'])
2878
2879 for f in input_api.AffectedSourceFiles(sources):
2880 for line_num, line in f.ChangedContents():
2881 if build_type_check_pattern.search(line):
2882 errors.append("%s:%d" % (f.LocalPath(), line_num))
2883
2884 results = []
2885
2886 if errors:
2887 results.append(output_api.PresubmitPromptWarning(
2888 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
2889 ' Please use BuildInfo.isDebugAndroid() instead.',
2890 errors))
2891
2892 return results
jbriance9e12f162016-11-25 07:57:502893
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492894# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:292895def _CheckAndroidToastUsage(input_api, output_api):
2896 """Checks that code uses org.chromium.ui.widget.Toast instead of
2897 android.widget.Toast (Chromium Toast doesn't force hardware
2898 acceleration on low-end devices, saving memory).
2899 """
2900 toast_import_pattern = input_api.re.compile(
2901 r'^import android\.widget\.Toast;$')
2902
2903 errors = []
2904
2905 sources = lambda affected_file: input_api.FilterSourceFile(
2906 affected_file,
2907 black_list=(_EXCLUDED_PATHS +
2908 _TEST_CODE_EXCLUDED_PATHS +
2909 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042910 (r'^chromecast[\\/].*',
2911 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492912 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:292913
2914 for f in input_api.AffectedSourceFiles(sources):
2915 for line_num, line in f.ChangedContents():
2916 if toast_import_pattern.search(line):
2917 errors.append("%s:%d" % (f.LocalPath(), line_num))
2918
2919 results = []
2920
2921 if errors:
2922 results.append(output_api.PresubmitError(
2923 'android.widget.Toast usage is detected. Android toasts use hardware'
2924 ' acceleration, and can be\ncostly on low-end devices. Please use'
2925 ' org.chromium.ui.widget.Toast instead.\n'
2926 'Contact [email protected] if you have any questions.',
2927 errors))
2928
2929 return results
2930
2931
dgnaa68d5e2015-06-10 10:08:222932def _CheckAndroidCrLogUsage(input_api, output_api):
2933 """Checks that new logs using org.chromium.base.Log:
2934 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512935 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222936 """
pkotwicza1dd0b002016-05-16 14:41:042937
torne89540622017-03-24 19:41:302938 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042939 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302940 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:042941 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:302942 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:042943 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
2944 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:092945 # The customtabs_benchmark is a small app that does not depend on Chromium
2946 # java pieces.
Egor Paskoce145c42018-09-28 19:31:042947 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:042948 ]
2949
dgnaa68d5e2015-06-10 10:08:222950 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122951 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2952 class_in_base_pattern = input_api.re.compile(
2953 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2954 has_some_log_import_pattern = input_api.re.compile(
2955 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222956 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122957 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222958 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512959 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222960 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222961
Vincent Scheib16d7b272015-09-15 18:09:072962 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222963 'or contact [email protected] for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492964 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:042965 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122966
dgnaa68d5e2015-06-10 10:08:222967 tag_decl_errors = []
2968 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122969 tag_errors = []
dgn38736db2015-09-18 19:20:512970 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122971 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222972
2973 for f in input_api.AffectedSourceFiles(sources):
2974 file_content = input_api.ReadFile(f)
2975 has_modified_logs = False
2976
2977 # Per line checks
dgn87d9fb62015-06-12 09:15:122978 if (cr_log_import_pattern.search(file_content) or
2979 (class_in_base_pattern.search(file_content) and
2980 not has_some_log_import_pattern.search(file_content))):
2981 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222982 for line_num, line in f.ChangedContents():
2983
2984 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122985 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222986 if match:
2987 has_modified_logs = True
2988
2989 # Make sure it uses "TAG"
2990 if not match.group('tag') == 'TAG':
2991 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122992 else:
2993 # Report non cr Log function calls in changed lines
2994 for line_num, line in f.ChangedContents():
2995 if log_call_pattern.search(line):
2996 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222997
2998 # Per file checks
2999 if has_modified_logs:
3000 # Make sure the tag is using the "cr" prefix and is not too long
3001 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513002 tag_name = match.group('name') if match else None
3003 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223004 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513005 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223006 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513007 elif '.' in tag_name:
3008 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223009
3010 results = []
3011 if tag_decl_errors:
3012 results.append(output_api.PresubmitPromptWarning(
3013 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513014 '"private static final String TAG = "<package tag>".\n'
3015 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223016 tag_decl_errors))
3017
3018 if tag_length_errors:
3019 results.append(output_api.PresubmitError(
3020 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513021 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223022 tag_length_errors))
3023
3024 if tag_errors:
3025 results.append(output_api.PresubmitPromptWarning(
3026 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3027 tag_errors))
3028
dgn87d9fb62015-06-12 09:15:123029 if util_log_errors:
dgn4401aa52015-04-29 16:26:173030 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123031 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3032 util_log_errors))
3033
dgn38736db2015-09-18 19:20:513034 if tag_with_dot_errors:
3035 results.append(output_api.PresubmitPromptWarning(
3036 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3037 tag_with_dot_errors))
3038
dgn4401aa52015-04-29 16:26:173039 return results
3040
3041
Yoland Yanb92fa522017-08-28 17:37:063042def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3043 """Checks that junit.framework.* is no longer used."""
3044 deprecated_junit_framework_pattern = input_api.re.compile(
3045 r'^import junit\.framework\..*;',
3046 input_api.re.MULTILINE)
3047 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493048 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063049 errors = []
3050 for f in input_api.AffectedFiles(sources):
3051 for line_num, line in f.ChangedContents():
3052 if deprecated_junit_framework_pattern.search(line):
3053 errors.append("%s:%d" % (f.LocalPath(), line_num))
3054
3055 results = []
3056 if errors:
3057 results.append(output_api.PresubmitError(
3058 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3059 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3060 ' if you have any question.', errors))
3061 return results
3062
3063
3064def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3065 """Checks that if new Java test classes have inheritance.
3066 Either the new test class is JUnit3 test or it is a JUnit4 test class
3067 with a base class, either case is undesirable.
3068 """
3069 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3070
3071 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493072 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063073 errors = []
3074 for f in input_api.AffectedFiles(sources):
3075 if not f.OldContents():
3076 class_declaration_start_flag = False
3077 for line_num, line in f.ChangedContents():
3078 if class_declaration_pattern.search(line):
3079 class_declaration_start_flag = True
3080 if class_declaration_start_flag and ' extends ' in line:
3081 errors.append('%s:%d' % (f.LocalPath(), line_num))
3082 if '{' in line:
3083 class_declaration_start_flag = False
3084
3085 results = []
3086 if errors:
3087 results.append(output_api.PresubmitPromptWarning(
3088 'The newly created files include Test classes that inherits from base'
3089 ' class. Please do not use inheritance in JUnit4 tests or add new'
3090 ' JUnit3 tests. Contact [email protected] if you have any'
3091 ' questions.', errors))
3092 return results
3093
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203094
yolandyan45001472016-12-21 21:12:423095def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3096 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3097 deprecated_annotation_import_pattern = input_api.re.compile(
3098 r'^import android\.test\.suitebuilder\.annotation\..*;',
3099 input_api.re.MULTILINE)
3100 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493101 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423102 errors = []
3103 for f in input_api.AffectedFiles(sources):
3104 for line_num, line in f.ChangedContents():
3105 if deprecated_annotation_import_pattern.search(line):
3106 errors.append("%s:%d" % (f.LocalPath(), line_num))
3107
3108 results = []
3109 if errors:
3110 results.append(output_api.PresubmitError(
3111 'Annotations in android.test.suitebuilder.annotation have been'
3112 ' deprecated since API level 24. Please use android.support.test.filters'
3113 ' from //third_party/android_support_test_runner:runner_java instead.'
3114 ' Contact [email protected] if you have any questions.', errors))
3115 return results
3116
3117
agrieve7b6479d82015-10-07 14:24:223118def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3119 """Checks if MDPI assets are placed in a correct directory."""
3120 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3121 ('/res/drawable/' in f.LocalPath() or
3122 '/res/drawable-ldrtl/' in f.LocalPath()))
3123 errors = []
3124 for f in input_api.AffectedFiles(include_deletes=False,
3125 file_filter=file_filter):
3126 errors.append(' %s' % f.LocalPath())
3127
3128 results = []
3129 if errors:
3130 results.append(output_api.PresubmitError(
3131 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3132 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3133 '/res/drawable-ldrtl/.\n'
3134 'Contact [email protected] if you have questions.', errors))
3135 return results
3136
3137
Nate Fischer535972b2017-09-16 01:06:183138def _CheckAndroidWebkitImports(input_api, output_api):
3139 """Checks that code uses org.chromium.base.Callback instead of
3140 android.widget.ValueCallback except in the WebView glue layer.
3141 """
3142 valuecallback_import_pattern = input_api.re.compile(
3143 r'^import android\.webkit\.ValueCallback;$')
3144
3145 errors = []
3146
3147 sources = lambda affected_file: input_api.FilterSourceFile(
3148 affected_file,
3149 black_list=(_EXCLUDED_PATHS +
3150 _TEST_CODE_EXCLUDED_PATHS +
3151 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043152 (r'^android_webview[\\/]glue[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493153 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183154
3155 for f in input_api.AffectedSourceFiles(sources):
3156 for line_num, line in f.ChangedContents():
3157 if valuecallback_import_pattern.search(line):
3158 errors.append("%s:%d" % (f.LocalPath(), line_num))
3159
3160 results = []
3161
3162 if errors:
3163 results.append(output_api.PresubmitError(
3164 'android.webkit.ValueCallback usage is detected outside of the glue'
3165 ' layer. To stay compatible with the support library, android.webkit.*'
3166 ' classes should only be used inside the glue layer and'
3167 ' org.chromium.base.Callback should be used instead.',
3168 errors))
3169
3170 return results
3171
3172
Becky Zhou7c69b50992018-12-10 19:37:573173def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3174 """Checks Android XML styles """
3175 import sys
3176 original_sys_path = sys.path
3177 try:
3178 sys.path = sys.path + [input_api.os_path.join(
3179 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3180 import checkxmlstyle
3181 finally:
3182 # Restore sys.path to what it was before.
3183 sys.path = original_sys_path
3184
3185 if is_check_on_upload:
3186 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3187 else:
3188 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3189
3190
agrievef32bcc72016-04-04 14:57:403191class PydepsChecker(object):
3192 def __init__(self, input_api, pydeps_files):
3193 self._file_cache = {}
3194 self._input_api = input_api
3195 self._pydeps_files = pydeps_files
3196
3197 def _LoadFile(self, path):
3198 """Returns the list of paths within a .pydeps file relative to //."""
3199 if path not in self._file_cache:
3200 with open(path) as f:
3201 self._file_cache[path] = f.read()
3202 return self._file_cache[path]
3203
3204 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3205 """Returns an interable of paths within the .pydep, relativized to //."""
3206 os_path = self._input_api.os_path
3207 pydeps_dir = os_path.dirname(pydeps_path)
3208 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3209 if not l.startswith('*'))
3210 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3211
3212 def _CreateFilesToPydepsMap(self):
3213 """Returns a map of local_path -> list_of_pydeps."""
3214 ret = {}
3215 for pydep_local_path in self._pydeps_files:
3216 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3217 ret.setdefault(path, []).append(pydep_local_path)
3218 return ret
3219
3220 def ComputeAffectedPydeps(self):
3221 """Returns an iterable of .pydeps files that might need regenerating."""
3222 affected_pydeps = set()
3223 file_to_pydeps_map = None
3224 for f in self._input_api.AffectedFiles(include_deletes=True):
3225 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463226 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3227 # subrepositories. We can't figure out which files change, so re-check
3228 # all files.
3229 # Changes to print_python_deps.py affect all .pydeps.
3230 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403231 return self._pydeps_files
3232 elif local_path.endswith('.pydeps'):
3233 if local_path in self._pydeps_files:
3234 affected_pydeps.add(local_path)
3235 elif local_path.endswith('.py'):
3236 if file_to_pydeps_map is None:
3237 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3238 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3239 return affected_pydeps
3240
3241 def DetermineIfStale(self, pydeps_path):
3242 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413243 import difflib
John Budorick47ca3fe2018-02-10 00:53:103244 import os
3245
agrievef32bcc72016-04-04 14:57:403246 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3247 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103248 env = dict(os.environ)
3249 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403250 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103251 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413252 old_contents = old_pydeps_data[2:]
3253 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403254 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413255 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403256
3257
Tibor Goldschwendt360793f72019-06-25 18:23:493258def _ParseGclientArgs():
3259 args = {}
3260 with open('build/config/gclient_args.gni', 'r') as f:
3261 for line in f:
3262 line = line.strip()
3263 if not line or line.startswith('#'):
3264 continue
3265 attribute, value = line.split('=')
3266 args[attribute.strip()] = value.strip()
3267 return args
3268
3269
agrievef32bcc72016-04-04 14:57:403270def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3271 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403272 # This check is for Python dependency lists (.pydeps files), and involves
3273 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3274 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283275 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003276 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493277 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403278 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3279 results = []
3280 # First, check for new / deleted .pydeps.
3281 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033282 # Check whether we are running the presubmit check for a file in src.
3283 # f.LocalPath is relative to repo (src, or internal repo).
3284 # os_path.exists is relative to src repo.
3285 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3286 # to src and we can conclude that the pydeps is in src.
3287 if input_api.os_path.exists(f.LocalPath()):
3288 if f.LocalPath().endswith('.pydeps'):
3289 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3290 results.append(output_api.PresubmitError(
3291 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3292 'remove %s' % f.LocalPath()))
3293 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3294 results.append(output_api.PresubmitError(
3295 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3296 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403297
3298 if results:
3299 return results
3300
3301 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3302
3303 for pydep_path in checker.ComputeAffectedPydeps():
3304 try:
phajdan.jr0d9878552016-11-04 10:49:413305 result = checker.DetermineIfStale(pydep_path)
3306 if result:
3307 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403308 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413309 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3310 'To regenerate, run:\n\n %s' %
3311 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403312 except input_api.subprocess.CalledProcessError as error:
3313 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3314 long_text=error.output)]
3315
3316 return results
3317
3318
glidere61efad2015-02-18 17:39:433319def _CheckSingletonInHeaders(input_api, output_api):
3320 """Checks to make sure no header files have |Singleton<|."""
3321 def FileFilter(affected_file):
3322 # It's ok for base/memory/singleton.h to have |Singleton<|.
3323 black_list = (_EXCLUDED_PATHS +
3324 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043325 (r"^base[\\/]memory[\\/]singleton\.h$",
3326 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473327 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433328 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3329
sergeyu34d21222015-09-16 00:11:443330 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433331 files = []
3332 for f in input_api.AffectedSourceFiles(FileFilter):
3333 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3334 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3335 contents = input_api.ReadFile(f)
3336 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243337 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433338 pattern.search(line)):
3339 files.append(f)
3340 break
3341
3342 if files:
yolandyandaabc6d2016-04-18 18:29:393343 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443344 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433345 'Please move them to an appropriate source file so that the ' +
3346 'template gets instantiated in a single compilation unit.',
3347 files) ]
3348 return []
3349
3350
[email protected]fd20b902014-05-09 02:14:533351_DEPRECATED_CSS = [
3352 # Values
3353 ( "-webkit-box", "flex" ),
3354 ( "-webkit-inline-box", "inline-flex" ),
3355 ( "-webkit-flex", "flex" ),
3356 ( "-webkit-inline-flex", "inline-flex" ),
3357 ( "-webkit-min-content", "min-content" ),
3358 ( "-webkit-max-content", "max-content" ),
3359
3360 # Properties
3361 ( "-webkit-background-clip", "background-clip" ),
3362 ( "-webkit-background-origin", "background-origin" ),
3363 ( "-webkit-background-size", "background-size" ),
3364 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443365 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533366
3367 # Functions
3368 ( "-webkit-gradient", "gradient" ),
3369 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3370 ( "-webkit-linear-gradient", "linear-gradient" ),
3371 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3372 ( "-webkit-radial-gradient", "radial-gradient" ),
3373 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3374]
3375
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203376
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493377# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243378def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533379 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253380 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343381 documentation and iOS CSS for dom distiller
3382 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253383 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533384 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493385 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253386 black_list = (_EXCLUDED_PATHS +
3387 _TEST_CODE_EXCLUDED_PATHS +
3388 input_api.DEFAULT_BLACK_LIST +
3389 (r"^chrome/common/extensions/docs",
3390 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343391 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443392 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253393 r"^native_client_sdk"))
3394 file_filter = lambda f: input_api.FilterSourceFile(
3395 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533396 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3397 for line_num, line in fpath.ChangedContents():
3398 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023399 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533400 results.append(output_api.PresubmitError(
3401 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3402 (fpath.LocalPath(), line_num, deprecated_value, value)))
3403 return results
3404
mohan.reddyf21db962014-10-16 12:26:473405
rlanday6802cf632017-05-30 17:48:363406def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363407 bad_files = {}
3408 for f in input_api.AffectedFiles(include_deletes=False):
3409 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493410 not f.LocalPath().startswith('third_party/blink') and
3411 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363412 continue
3413
Daniel Bratell65b033262019-04-23 08:17:063414 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363415 continue
3416
Vaclav Brozekd5de76a2018-03-17 07:57:503417 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363418 if "#include" in line and "../" in line]
3419 if not relative_includes:
3420 continue
3421 bad_files[f.LocalPath()] = relative_includes
3422
3423 if not bad_files:
3424 return []
3425
3426 error_descriptions = []
3427 for file_path, bad_lines in bad_files.iteritems():
3428 error_description = file_path
3429 for line in bad_lines:
3430 error_description += '\n ' + line
3431 error_descriptions.append(error_description)
3432
3433 results = []
3434 results.append(output_api.PresubmitError(
3435 'You added one or more relative #include paths (including "../").\n'
3436 'These shouldn\'t be used because they can be used to include headers\n'
3437 'from code that\'s not correctly specified as a dependency in the\n'
3438 'relevant BUILD.gn file(s).',
3439 error_descriptions))
3440
3441 return results
3442
Takeshi Yoshinoe387aa32017-08-02 13:16:133443
Daniel Bratell65b033262019-04-23 08:17:063444def _CheckForCcIncludes(input_api, output_api):
3445 """Check that nobody tries to include a cc file. It's a relatively
3446 common error which results in duplicate symbols in object
3447 files. This may not always break the build until someone later gets
3448 very confusing linking errors."""
3449 results = []
3450 for f in input_api.AffectedFiles(include_deletes=False):
3451 # We let third_party code do whatever it wants
3452 if (f.LocalPath().startswith('third_party') and
3453 not f.LocalPath().startswith('third_party/blink') and
3454 not f.LocalPath().startswith('third_party\\blink')):
3455 continue
3456
3457 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3458 continue
3459
3460 for _, line in f.ChangedContents():
3461 if line.startswith('#include "'):
3462 included_file = line.split('"')[1]
3463 if _IsCPlusPlusFile(input_api, included_file):
3464 # The most common naming for external files with C++ code,
3465 # apart from standard headers, is to call them foo.inc, but
3466 # Chromium sometimes uses foo-inc.cc so allow that as well.
3467 if not included_file.endswith(('.h', '-inc.cc')):
3468 results.append(output_api.PresubmitError(
3469 'Only header files or .inc files should be included in other\n'
3470 'C++ files. Compiling the contents of a cc file more than once\n'
3471 'will cause duplicate information in the build which may later\n'
3472 'result in strange link_errors.\n' +
3473 f.LocalPath() + ':\n ' +
3474 line))
3475
3476 return results
3477
3478
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203479def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3480 if not isinstance(key, ast.Str):
3481 return 'Key at line %d must be a string literal' % key.lineno
3482 if not isinstance(value, ast.Dict):
3483 return 'Value at line %d must be a dict' % value.lineno
3484 if len(value.keys) != 1:
3485 return 'Dict at line %d must have single entry' % value.lineno
3486 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3487 return (
3488 'Entry at line %d must have a string literal \'filepath\' as key' %
3489 value.lineno)
3490 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133491
Takeshi Yoshinoe387aa32017-08-02 13:16:133492
Sergey Ulanov4af16052018-11-08 02:41:463493def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203494 if not isinstance(key, ast.Str):
3495 return 'Key at line %d must be a string literal' % key.lineno
3496 if not isinstance(value, ast.List):
3497 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463498 for element in value.elts:
3499 if not isinstance(element, ast.Str):
3500 return 'Watchlist elements on line %d is not a string' % key.lineno
3501 if not email_regex.match(element.s):
3502 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3503 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203504 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133505
Takeshi Yoshinoe387aa32017-08-02 13:16:133506
Sergey Ulanov4af16052018-11-08 02:41:463507def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203508 mismatch_template = (
3509 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3510 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133511
Sergey Ulanov4af16052018-11-08 02:41:463512 email_regex = input_api.re.compile(
3513 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3514
3515 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203516 i = 0
3517 last_key = ''
3518 while True:
3519 if i >= len(wd_dict.keys):
3520 if i >= len(w_dict.keys):
3521 return None
3522 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3523 elif i >= len(w_dict.keys):
3524 return (
3525 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133526
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203527 wd_key = wd_dict.keys[i]
3528 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133529
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203530 result = _CheckWatchlistDefinitionsEntrySyntax(
3531 wd_key, wd_dict.values[i], ast)
3532 if result is not None:
3533 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133534
Sergey Ulanov4af16052018-11-08 02:41:463535 result = _CheckWatchlistsEntrySyntax(
3536 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203537 if result is not None:
3538 return 'Bad entry in WATCHLISTS dict: %s' % result
3539
3540 if wd_key.s != w_key.s:
3541 return mismatch_template % (
3542 '%s at line %d' % (wd_key.s, wd_key.lineno),
3543 '%s at line %d' % (w_key.s, w_key.lineno))
3544
3545 if wd_key.s < last_key:
3546 return (
3547 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3548 (wd_key.lineno, w_key.lineno))
3549 last_key = wd_key.s
3550
3551 i = i + 1
3552
3553
Sergey Ulanov4af16052018-11-08 02:41:463554def _CheckWATCHLISTSSyntax(expression, input_api):
3555 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203556 if not isinstance(expression, ast.Expression):
3557 return 'WATCHLISTS file must contain a valid expression'
3558 dictionary = expression.body
3559 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3560 return 'WATCHLISTS file must have single dict with exactly two entries'
3561
3562 first_key = dictionary.keys[0]
3563 first_value = dictionary.values[0]
3564 second_key = dictionary.keys[1]
3565 second_value = dictionary.values[1]
3566
3567 if (not isinstance(first_key, ast.Str) or
3568 first_key.s != 'WATCHLIST_DEFINITIONS' or
3569 not isinstance(first_value, ast.Dict)):
3570 return (
3571 'The first entry of the dict in WATCHLISTS file must be '
3572 'WATCHLIST_DEFINITIONS dict')
3573
3574 if (not isinstance(second_key, ast.Str) or
3575 second_key.s != 'WATCHLISTS' or
3576 not isinstance(second_value, ast.Dict)):
3577 return (
3578 'The second entry of the dict in WATCHLISTS file must be '
3579 'WATCHLISTS dict')
3580
Sergey Ulanov4af16052018-11-08 02:41:463581 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133582
3583
3584def _CheckWATCHLISTS(input_api, output_api):
3585 for f in input_api.AffectedFiles(include_deletes=False):
3586 if f.LocalPath() == 'WATCHLISTS':
3587 contents = input_api.ReadFile(f, 'r')
3588
3589 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203590 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133591 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203592 # Get an AST tree for it and scan the tree for detailed style checking.
3593 expression = input_api.ast.parse(
3594 contents, filename='WATCHLISTS', mode='eval')
3595 except ValueError as e:
3596 return [output_api.PresubmitError(
3597 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3598 except SyntaxError as e:
3599 return [output_api.PresubmitError(
3600 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3601 except TypeError as e:
3602 return [output_api.PresubmitError(
3603 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133604
Sergey Ulanov4af16052018-11-08 02:41:463605 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203606 if result is not None:
3607 return [output_api.PresubmitError(result)]
3608 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133609
3610 return []
3611
3612
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193613def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3614 """Checks that newly added header files have corresponding GN changes.
3615 Note that this is only a heuristic. To be precise, run script:
3616 build/check_gn_headers.py.
3617 """
3618
3619 def headers(f):
3620 return input_api.FilterSourceFile(
3621 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3622
3623 new_headers = []
3624 for f in input_api.AffectedSourceFiles(headers):
3625 if f.Action() != 'A':
3626 continue
3627 new_headers.append(f.LocalPath())
3628
3629 def gn_files(f):
3630 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3631
3632 all_gn_changed_contents = ''
3633 for f in input_api.AffectedSourceFiles(gn_files):
3634 for _, line in f.ChangedContents():
3635 all_gn_changed_contents += line
3636
3637 problems = []
3638 for header in new_headers:
3639 basename = input_api.os_path.basename(header)
3640 if basename not in all_gn_changed_contents:
3641 problems.append(header)
3642
3643 if problems:
3644 return [output_api.PresubmitPromptWarning(
3645 'Missing GN changes for new header files', items=sorted(problems),
3646 long_text='Please double check whether newly added header files need '
3647 'corresponding changes in gn or gni files.\nThis checking is only a '
3648 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3649 'Read https://crbug.com/661774 for more info.')]
3650 return []
3651
3652
Michael Giuffridad3bc8672018-10-25 22:48:023653def _CheckCorrectProductNameInMessages(input_api, output_api):
3654 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3655
3656 This assumes we won't intentionally reference one product from the other
3657 product.
3658 """
3659 all_problems = []
3660 test_cases = [{
3661 "filename_postfix": "google_chrome_strings.grd",
3662 "correct_name": "Chrome",
3663 "incorrect_name": "Chromium",
3664 }, {
3665 "filename_postfix": "chromium_strings.grd",
3666 "correct_name": "Chromium",
3667 "incorrect_name": "Chrome",
3668 }]
3669
3670 for test_case in test_cases:
3671 problems = []
3672 filename_filter = lambda x: x.LocalPath().endswith(
3673 test_case["filename_postfix"])
3674
3675 # Check each new line. Can yield false positives in multiline comments, but
3676 # easier than trying to parse the XML because messages can have nested
3677 # children, and associating message elements with affected lines is hard.
3678 for f in input_api.AffectedSourceFiles(filename_filter):
3679 for line_num, line in f.ChangedContents():
3680 if "<message" in line or "<!--" in line or "-->" in line:
3681 continue
3682 if test_case["incorrect_name"] in line:
3683 problems.append(
3684 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3685
3686 if problems:
3687 message = (
3688 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3689 % (test_case["correct_name"], test_case["correct_name"],
3690 test_case["incorrect_name"]))
3691 all_problems.append(
3692 output_api.PresubmitPromptWarning(message, items=problems))
3693
3694 return all_problems
3695
3696
Dirk Pranke3c18a382019-03-15 01:07:513697def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3698 # TODO(crbug.com/941824): We need to make sure the entries in
3699 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3700 # so that users of //buildtools in other projects get the same tooling
3701 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3702 # support to gclient, we can eliminate the duplication and delete
3703 # this presubmit check.
3704
3705 # Update this regexp if new revisions are added to the files.
3706 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013707 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513708
3709 # If a user is changing one revision, they need to change the same
3710 # line in both files. This means that any given change should contain
3711 # exactly the same list of changed lines that match the regexps. The
3712 # replace(' ', '') call allows us to ignore whitespace changes to the
3713 # lines. The 'long_text' parameter to the error will contain the
3714 # list of changed lines in both files, which should make it easy enough
3715 # to spot the error without going overboard in this implementation.
3716 revs_changes = {
3717 'DEPS': {},
3718 'buildtools/DEPS': {},
3719 }
3720 long_text = ''
3721
3722 for f in input_api.AffectedFiles(
3723 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3724 for line_num, line in f.ChangedContents():
3725 if rev_regexp.search(line):
3726 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3727 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3728
3729 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3730 return [output_api.PresubmitError(
3731 'Change buildtools revisions in sync in both //DEPS and '
3732 '//buildtools/DEPS.', long_text=long_text + '\n')]
3733 else:
3734 return []
3735
3736
Daniel Bratell93eb6c62019-04-29 20:13:363737def _CheckForTooLargeFiles(input_api, output_api):
3738 """Avoid large files, especially binary files, in the repository since
3739 git doesn't scale well for those. They will be in everyone's repo
3740 clones forever, forever making Chromium slower to clone and work
3741 with."""
3742
3743 # Uploading files to cloud storage is not trivial so we don't want
3744 # to set the limit too low, but the upper limit for "normal" large
3745 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
3746 # anything over 20 MB is exceptional.
3747 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
3748
3749 too_large_files = []
3750 for f in input_api.AffectedFiles():
3751 # Check both added and modified files (but not deleted files).
3752 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:383753 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:363754 if size > TOO_LARGE_FILE_SIZE_LIMIT:
3755 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
3756
3757 if too_large_files:
3758 message = (
3759 'Do not commit large files to git since git scales badly for those.\n' +
3760 'Instead put the large files in cloud storage and use DEPS to\n' +
3761 'fetch them.\n' + '\n'.join(too_large_files)
3762 )
3763 return [output_api.PresubmitError(
3764 'Too large files found in commit', long_text=message + '\n')]
3765 else:
3766 return []
3767
Max Morozb47503b2019-08-08 21:03:273768
3769def _CheckFuzzTargets(input_api, output_api):
3770 """Checks specific for fuzz target sources."""
3771 EXPORTED_SYMBOLS = [
3772 'LLVMFuzzerInitialize',
3773 'LLVMFuzzerCustomMutator',
3774 'LLVMFuzzerCustomCrossOver',
3775 'LLVMFuzzerMutate',
3776 ]
3777
3778 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
3779
3780 def FilterFile(affected_file):
3781 """Ignore libFuzzer source code."""
3782 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
3783 black_list = r"^third_party[\\/]libFuzzer"
3784
3785 return input_api.FilterSourceFile(
3786 affected_file,
3787 white_list=[white_list],
3788 black_list=[black_list])
3789
3790 files_with_missing_header = []
3791 for f in input_api.AffectedSourceFiles(FilterFile):
3792 contents = input_api.ReadFile(f, 'r')
3793 if REQUIRED_HEADER in contents:
3794 continue
3795
3796 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
3797 files_with_missing_header.append(f.LocalPath())
3798
3799 if not files_with_missing_header:
3800 return []
3801
3802 long_text = (
3803 'If you define any of the libFuzzer optional functions (%s), it is '
3804 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
3805 'work incorrectly on Mac (crbug.com/687076).\nNote that '
3806 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
3807 'to access command line arguments passed to the fuzzer. Instead, prefer '
3808 'static initialization and shared resources as documented in '
3809 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
3810 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
3811 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
3812 )
3813
3814 return [output_api.PresubmitPromptWarning(
3815 message="Missing '%s' in:" % REQUIRED_HEADER,
3816 items=files_with_missing_header,
3817 long_text=long_text)]
3818
3819
dgnaa68d5e2015-06-10 10:08:223820def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:573821 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:223822 results = []
dgnaa68d5e2015-06-10 10:08:223823 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:173824 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:223825 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:293826 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:063827 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
3828 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:423829 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:183830 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:573831 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
3832 return results
3833
3834def _AndroidSpecificOnCommitChecks(input_api, output_api):
3835 """Groups commit checks that target android code."""
3836 results = []
3837 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:223838 return results
3839
3840
[email protected]22c9bd72011-03-27 16:47:393841def _CommonChecks(input_api, output_api):
3842 """Checks common to both upload and commit."""
3843 results = []
3844 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:383845 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:543846 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:083847
3848 author = input_api.change.author_email
3849 if author and author not in _KNOWN_ROBOTS:
3850 results.extend(
3851 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
3852
[email protected]55459852011-08-10 15:17:193853 results.extend(
[email protected]760deea2013-12-10 19:33:493854 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:233855 results.extend(
3856 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:543857 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:183858 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:343859 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:523860 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:223861 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:443862 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:593863 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:063864 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:123865 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:183866 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:223867 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:303868 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:493869 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:033870 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:493871 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:443872 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:273873 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:073874 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:543875 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:443876 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:393877 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:553878 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:043879 results.extend(
3880 input_api.canned_checks.CheckChangeHasNoTabs(
3881 input_api,
3882 output_api,
3883 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:403884 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:163885 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:083886 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:243887 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:473888 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:043889 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:053890 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:143891 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:233892 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:433893 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:403894 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:153895 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:173896 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:503897 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:363898 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:063899 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:133900 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:433901 results.extend(input_api.RunTests(
3902 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143903 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:023904 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:513905 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:363906 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:003907 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:243908
Vaclav Brozekcdc7defb2018-03-20 09:54:353909 for f in input_api.AffectedFiles():
3910 path, name = input_api.os_path.split(f.LocalPath())
3911 if name == 'PRESUBMIT.py':
3912 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:003913 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
3914 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:073915 # The PRESUBMIT.py file (and the directory containing it) might
3916 # have been affected by being moved or removed, so only try to
3917 # run the tests if they still exist.
3918 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
3919 input_api, output_api, full_path,
3920 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:393921 return results
[email protected]1f7b4172010-01-28 01:17:343922
[email protected]b337cb5b2011-01-23 21:24:053923
[email protected]b8079ae4a2012-12-05 19:56:493924def _CheckPatchFiles(input_api, output_api):
3925 problems = [f.LocalPath() for f in input_api.AffectedFiles()
3926 if f.LocalPath().endswith(('.orig', '.rej'))]
3927 if problems:
3928 return [output_api.PresubmitError(
3929 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:033930 else:
3931 return []
[email protected]b8079ae4a2012-12-05 19:56:493932
3933
Kent Tamura5a8755d2017-06-29 23:37:073934def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:213935 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
3936 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
3937 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:073938 include_re = input_api.re.compile(
3939 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
3940 extension_re = input_api.re.compile(r'\.[a-z]+$')
3941 errors = []
3942 for f in input_api.AffectedFiles():
3943 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
3944 continue
3945 found_line_number = None
3946 found_macro = None
3947 for line_num, line in f.ChangedContents():
3948 match = macro_re.search(line)
3949 if match:
3950 found_line_number = line_num
3951 found_macro = match.group(2)
3952 break
3953 if not found_line_number:
3954 continue
3955
3956 found_include = False
3957 for line in f.NewContents():
3958 if include_re.search(line):
3959 found_include = True
3960 break
3961 if found_include:
3962 continue
3963
3964 if not f.LocalPath().endswith('.h'):
3965 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
3966 try:
3967 content = input_api.ReadFile(primary_header_path, 'r')
3968 if include_re.search(content):
3969 continue
3970 except IOError:
3971 pass
3972 errors.append('%s:%d %s macro is used without including build/'
3973 'build_config.h.'
3974 % (f.LocalPath(), found_line_number, found_macro))
3975 if errors:
3976 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
3977 return []
3978
3979
[email protected]b00342e7f2013-03-26 16:21:543980def _DidYouMeanOSMacro(bad_macro):
3981 try:
3982 return {'A': 'OS_ANDROID',
3983 'B': 'OS_BSD',
3984 'C': 'OS_CHROMEOS',
3985 'F': 'OS_FREEBSD',
3986 'L': 'OS_LINUX',
3987 'M': 'OS_MACOSX',
3988 'N': 'OS_NACL',
3989 'O': 'OS_OPENBSD',
3990 'P': 'OS_POSIX',
3991 'S': 'OS_SOLARIS',
3992 'W': 'OS_WIN'}[bad_macro[3].upper()]
3993 except KeyError:
3994 return ''
3995
3996
3997def _CheckForInvalidOSMacrosInFile(input_api, f):
3998 """Check for sensible looking, totally invalid OS macros."""
3999 preprocessor_statement = input_api.re.compile(r'^\s*#')
4000 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4001 results = []
4002 for lnum, line in f.ChangedContents():
4003 if preprocessor_statement.search(line):
4004 for match in os_macro.finditer(line):
4005 if not match.group(1) in _VALID_OS_MACROS:
4006 good = _DidYouMeanOSMacro(match.group(1))
4007 did_you_mean = ' (did you mean %s?)' % good if good else ''
4008 results.append(' %s:%d %s%s' % (f.LocalPath(),
4009 lnum,
4010 match.group(1),
4011 did_you_mean))
4012 return results
4013
4014
4015def _CheckForInvalidOSMacros(input_api, output_api):
4016 """Check all affected files for invalid OS macros."""
4017 bad_macros = []
tzik3f295992018-12-04 20:32:234018 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474019 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544020 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4021
4022 if not bad_macros:
4023 return []
4024
4025 return [output_api.PresubmitError(
4026 'Possibly invalid OS macro[s] found. Please fix your code\n'
4027 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4028
lliabraa35bab3932014-10-01 12:16:444029
4030def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4031 """Check all affected files for invalid "if defined" macros."""
4032 ALWAYS_DEFINED_MACROS = (
4033 "TARGET_CPU_PPC",
4034 "TARGET_CPU_PPC64",
4035 "TARGET_CPU_68K",
4036 "TARGET_CPU_X86",
4037 "TARGET_CPU_ARM",
4038 "TARGET_CPU_MIPS",
4039 "TARGET_CPU_SPARC",
4040 "TARGET_CPU_ALPHA",
4041 "TARGET_IPHONE_SIMULATOR",
4042 "TARGET_OS_EMBEDDED",
4043 "TARGET_OS_IPHONE",
4044 "TARGET_OS_MAC",
4045 "TARGET_OS_UNIX",
4046 "TARGET_OS_WIN32",
4047 )
4048 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4049 results = []
4050 for lnum, line in f.ChangedContents():
4051 for match in ifdef_macro.finditer(line):
4052 if match.group(1) in ALWAYS_DEFINED_MACROS:
4053 always_defined = ' %s is always defined. ' % match.group(1)
4054 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4055 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4056 lnum,
4057 always_defined,
4058 did_you_mean))
4059 return results
4060
4061
4062def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4063 """Check all affected files for invalid "if defined" macros."""
4064 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054065 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444066 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054067 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214068 continue
lliabraa35bab3932014-10-01 12:16:444069 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4070 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4071
4072 if not bad_macros:
4073 return []
4074
4075 return [output_api.PresubmitError(
4076 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4077 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4078 bad_macros)]
4079
4080
mlamouria82272622014-09-16 18:45:044081def _CheckForIPCRules(input_api, output_api):
4082 """Check for same IPC rules described in
4083 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4084 """
4085 base_pattern = r'IPC_ENUM_TRAITS\('
4086 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4087 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4088
4089 problems = []
4090 for f in input_api.AffectedSourceFiles(None):
4091 local_path = f.LocalPath()
4092 if not local_path.endswith('.h'):
4093 continue
4094 for line_number, line in f.ChangedContents():
4095 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4096 problems.append(
4097 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4098
4099 if problems:
4100 return [output_api.PresubmitPromptWarning(
4101 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4102 else:
4103 return []
4104
[email protected]b00342e7f2013-03-26 16:21:544105
Stephen Martinis97a394142018-06-07 23:06:054106def _CheckForLongPathnames(input_api, output_api):
4107 """Check to make sure no files being submitted have long paths.
4108 This causes issues on Windows.
4109 """
4110 problems = []
4111 for f in input_api.AffectedSourceFiles(None):
4112 local_path = f.LocalPath()
4113 # Windows has a path limit of 260 characters. Limit path length to 200 so
4114 # that we have some extra for the prefix on dev machines and the bots.
4115 if len(local_path) > 200:
4116 problems.append(local_path)
4117
4118 if problems:
4119 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4120 else:
4121 return []
4122
4123
Daniel Bratell8ba52722018-03-02 16:06:144124def _CheckForIncludeGuards(input_api, output_api):
4125 """Check that header files have proper guards against multiple inclusion.
4126 If a file should not have such guards (and it probably should) then it
4127 should include the string "no-include-guard-because-multiply-included".
4128 """
Daniel Bratell6a75baef62018-06-04 10:04:454129 def is_chromium_header_file(f):
4130 # We only check header files under the control of the Chromium
4131 # project. That is, those outside third_party apart from
4132 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324133 # We also exclude *_message_generator.h headers as they use
4134 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454135 file_with_path = input_api.os_path.normpath(f.LocalPath())
4136 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324137 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454138 (not file_with_path.startswith('third_party') or
4139 file_with_path.startswith(
4140 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144141
4142 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344143 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144144
4145 errors = []
4146
Daniel Bratell6a75baef62018-06-04 10:04:454147 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144148 guard_name = None
4149 guard_line_number = None
4150 seen_guard_end = False
4151
4152 file_with_path = input_api.os_path.normpath(f.LocalPath())
4153 base_file_name = input_api.os_path.splitext(
4154 input_api.os_path.basename(file_with_path))[0]
4155 upper_base_file_name = base_file_name.upper()
4156
4157 expected_guard = replace_special_with_underscore(
4158 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144159
4160 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574161 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4162 # are too many (1000+) files with slight deviations from the
4163 # coding style. The most important part is that the include guard
4164 # is there, and that it's unique, not the name so this check is
4165 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144166 #
4167 # As code becomes more uniform, this could be made stricter.
4168
4169 guard_name_pattern_list = [
4170 # Anything with the right suffix (maybe with an extra _).
4171 r'\w+_H__?',
4172
Daniel Bratell39b5b062018-05-16 18:09:574173 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144174 r'\w+_h',
4175
4176 # Anything including the uppercase name of the file.
4177 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4178 upper_base_file_name)) + r'\w*',
4179 ]
4180 guard_name_pattern = '|'.join(guard_name_pattern_list)
4181 guard_pattern = input_api.re.compile(
4182 r'#ifndef\s+(' + guard_name_pattern + ')')
4183
4184 for line_number, line in enumerate(f.NewContents()):
4185 if 'no-include-guard-because-multiply-included' in line:
4186 guard_name = 'DUMMY' # To not trigger check outside the loop.
4187 break
4188
4189 if guard_name is None:
4190 match = guard_pattern.match(line)
4191 if match:
4192 guard_name = match.group(1)
4193 guard_line_number = line_number
4194
Daniel Bratell39b5b062018-05-16 18:09:574195 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454196 # don't match the chromium style guide, but new files should
4197 # get it right.
4198 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574199 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144200 errors.append(output_api.PresubmitPromptWarning(
4201 'Header using the wrong include guard name %s' % guard_name,
4202 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell39b5b062018-05-16 18:09:574203 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144204 else:
4205 # The line after #ifndef should have a #define of the same name.
4206 if line_number == guard_line_number + 1:
4207 expected_line = '#define %s' % guard_name
4208 if line != expected_line:
4209 errors.append(output_api.PresubmitPromptWarning(
4210 'Missing "%s" for include guard' % expected_line,
4211 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4212 'Expected: %r\nGot: %r' % (expected_line, line)))
4213
4214 if not seen_guard_end and line == '#endif // %s' % guard_name:
4215 seen_guard_end = True
4216 elif seen_guard_end:
4217 if line.strip() != '':
4218 errors.append(output_api.PresubmitPromptWarning(
4219 'Include guard %s not covering the whole file' % (
4220 guard_name), [f.LocalPath()]))
4221 break # Nothing else to check and enough to warn once.
4222
4223 if guard_name is None:
4224 errors.append(output_api.PresubmitPromptWarning(
4225 'Missing include guard %s' % expected_guard,
4226 [f.LocalPath()],
4227 'Missing include guard in %s\n'
4228 'Recommended name: %s\n'
4229 'This check can be disabled by having the string\n'
4230 'no-include-guard-because-multiply-included in the header.' %
4231 (f.LocalPath(), expected_guard)))
4232
4233 return errors
4234
4235
mostynbb639aca52015-01-07 20:31:234236def _CheckForWindowsLineEndings(input_api, output_api):
4237 """Check source code and known ascii text files for Windows style line
4238 endings.
4239 """
earthdok1b5e0ee2015-03-10 15:19:104240 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234241
4242 file_inclusion_pattern = (
4243 known_text_files,
4244 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4245 )
4246
mostynbb639aca52015-01-07 20:31:234247 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534248 source_file_filter = lambda f: input_api.FilterSourceFile(
4249 f, white_list=file_inclusion_pattern, black_list=None)
4250 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504251 include_file = False
4252 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234253 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504254 include_file = True
4255 if include_file:
4256 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234257
4258 if problems:
4259 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4260 'these files to contain Windows style line endings?\n' +
4261 '\n'.join(problems))]
4262
4263 return []
4264
4265
Vaclav Brozekd5de76a2018-03-17 07:57:504266def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134267 """Checks that all source files use SYSLOG properly."""
4268 syslog_files = []
4269 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564270 for line_number, line in f.ChangedContents():
4271 if 'SYSLOG' in line:
4272 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4273
pastarmovj89f7ee12016-09-20 14:58:134274 if syslog_files:
4275 return [output_api.PresubmitPromptWarning(
4276 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4277 ' calls.\nFiles to check:\n', items=syslog_files)]
4278 return []
4279
4280
[email protected]1f7b4172010-01-28 01:17:344281def CheckChangeOnUpload(input_api, output_api):
4282 results = []
4283 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474284 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284285 results.extend(
jam93a6ee792017-02-08 23:59:224286 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194287 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224288 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134289 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164290 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534291 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194292 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274293 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544294 return results
[email protected]ca8d1982009-02-19 16:33:124295
4296
[email protected]1bfb8322014-04-23 01:02:414297def GetTryServerMasterForBot(bot):
4298 """Returns the Try Server master for the given bot.
4299
[email protected]0bb112362014-07-26 04:38:324300 It tries to guess the master from the bot name, but may still fail
4301 and return None. There is no longer a default master.
4302 """
4303 # Potentially ambiguous bot names are listed explicitly.
4304 master_map = {
tandriie5587792016-07-14 00:34:504305 'chromium_presubmit': 'master.tryserver.chromium.linux',
4306 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414307 }
[email protected]0bb112362014-07-26 04:38:324308 master = master_map.get(bot)
4309 if not master:
wnwen4fbaab82016-05-25 12:54:364310 if 'android' in bot:
tandriie5587792016-07-14 00:34:504311 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364312 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504313 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324314 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504315 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324316 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504317 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324318 return master
[email protected]1bfb8322014-04-23 01:02:414319
4320
[email protected]ca8d1982009-02-19 16:33:124321def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544322 results = []
[email protected]1f7b4172010-01-28 01:17:344323 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574324 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544325 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274326 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344327 input_api,
4328 output_api,
[email protected]2fdd1f362013-01-16 03:56:034329 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274330
jam93a6ee792017-02-08 23:59:224331 results.extend(
4332 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544333 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4334 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414335 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4336 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544337 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144338
4339
4340def _CheckTranslationScreenshots(input_api, output_api):
4341 PART_FILE_TAG = "part"
4342 import os
4343 import sys
4344 from io import StringIO
4345
4346 try:
4347 old_sys_path = sys.path
4348 sys.path = sys.path + [input_api.os_path.join(
4349 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4350 import grit.grd_reader
4351 import grit.node.message
4352 import grit.util
4353 finally:
4354 sys.path = old_sys_path
4355
4356 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4357 """Load the grd file and return a dict of message ids to messages.
4358
4359 Ignores any nested grdp files pointed by <part> tag.
4360 """
4361 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4362 stop_after=None, first_ids_file=None,
Julian Pastarmov4f7af532019-07-17 19:25:374363 debug=False, defines={'_chromium': 1},
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144364 tags_to_ignore=set([PART_FILE_TAG]))
4365 return {
4366 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4367 grit.node.message.MessageNode)
4368 }
4369
4370 def _GetGrdpMessagesFromString(grdp_string):
4371 """Parses the contents of a grdp file given in grdp_string.
4372
4373 grd_reader can't parse grdp files directly. Instead, this creates a
4374 temporary directory with a grd file pointing to the grdp file, and loads the
4375 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4376 """
4377 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4378 <grit latest_public_release="1" current_release="1">
4379 <release seq="1">
4380 <messages>
4381 <part file="sub.grdp" />
4382 </messages>
4383 </release>
4384 </grit>
4385 """
4386 with grit.util.TempDir({'main.grd': WRAPPER,
4387 'sub.grdp': grdp_string}) as temp_dir:
4388 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4389
4390 new_or_added_paths = set(f.LocalPath()
4391 for f in input_api.AffectedFiles()
4392 if (f.Action() == 'A' or f.Action() == 'M'))
4393 removed_paths = set(f.LocalPath()
4394 for f in input_api.AffectedFiles(include_deletes=True)
4395 if f.Action() == 'D')
4396
4397 affected_grds = [f for f in input_api.AffectedFiles()
4398 if (f.LocalPath().endswith('.grd') or
4399 f.LocalPath().endswith('.grdp'))]
4400 affected_png_paths = [f.AbsoluteLocalPath()
4401 for f in input_api.AffectedFiles()
4402 if (f.LocalPath().endswith('.png'))]
4403
4404 # Check for screenshots. Developers can upload screenshots using
4405 # tools/translation/upload_screenshots.py which finds and uploads
4406 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4407 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4408 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4409 #
4410 # The logic here is as follows:
4411 #
4412 # - If the CL has a .png file under the screenshots directory for a grd
4413 # file, warn the developer. Actual images should never be checked into the
4414 # Chrome repo.
4415 #
4416 # - If the CL contains modified or new messages in grd files and doesn't
4417 # contain the corresponding .sha1 files, warn the developer to add images
4418 # and upload them via tools/translation/upload_screenshots.py.
4419 #
4420 # - If the CL contains modified or new messages in grd files and the
4421 # corresponding .sha1 files, everything looks good.
4422 #
4423 # - If the CL contains removed messages in grd files but the corresponding
4424 # .sha1 files aren't removed, warn the developer to remove them.
4425 unnecessary_screenshots = []
4426 missing_sha1 = []
4427 unnecessary_sha1_files = []
4428
4429
4430 def _CheckScreenshotAdded(screenshots_dir, message_id):
4431 sha1_path = input_api.os_path.join(
4432 screenshots_dir, message_id + '.png.sha1')
4433 if sha1_path not in new_or_added_paths:
4434 missing_sha1.append(sha1_path)
4435
4436
4437 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4438 sha1_path = input_api.os_path.join(
4439 screenshots_dir, message_id + '.png.sha1')
4440 if sha1_path not in removed_paths:
4441 unnecessary_sha1_files.append(sha1_path)
4442
4443
4444 for f in affected_grds:
4445 file_path = f.LocalPath()
4446 old_id_to_msg_map = {}
4447 new_id_to_msg_map = {}
4448 if file_path.endswith('.grdp'):
4449 if f.OldContents():
4450 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394451 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144452 if f.NewContents():
4453 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394454 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144455 else:
4456 if f.OldContents():
4457 old_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394458 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144459 if f.NewContents():
4460 new_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394461 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144462
4463 # Compute added, removed and modified message IDs.
4464 old_ids = set(old_id_to_msg_map)
4465 new_ids = set(new_id_to_msg_map)
4466 added_ids = new_ids - old_ids
4467 removed_ids = old_ids - new_ids
4468 modified_ids = set([])
4469 for key in old_ids.intersection(new_ids):
4470 if (old_id_to_msg_map[key].FormatXml()
4471 != new_id_to_msg_map[key].FormatXml()):
4472 modified_ids.add(key)
4473
4474 grd_name, ext = input_api.os_path.splitext(
4475 input_api.os_path.basename(file_path))
4476 screenshots_dir = input_api.os_path.join(
4477 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4478
4479 # Check the screenshot directory for .png files. Warn if there is any.
4480 for png_path in affected_png_paths:
4481 if png_path.startswith(screenshots_dir):
4482 unnecessary_screenshots.append(png_path)
4483
4484 for added_id in added_ids:
4485 _CheckScreenshotAdded(screenshots_dir, added_id)
4486
4487 for modified_id in modified_ids:
4488 _CheckScreenshotAdded(screenshots_dir, modified_id)
4489
4490 for removed_id in removed_ids:
4491 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4492
4493 results = []
4494 if unnecessary_screenshots:
4495 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394496 'Do not include actual screenshots in the changelist. Run '
4497 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144498 sorted(unnecessary_screenshots)))
4499
4500 if missing_sha1:
4501 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394502 'You are adding or modifying UI strings.\n'
4503 'To ensure the best translations, take screenshots of the relevant UI '
4504 '(https://g.co/chrome/translation) and add these files to your '
4505 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144506
4507 if unnecessary_sha1_files:
4508 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394509 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144510 sorted(unnecessary_sha1_files)))
4511
4512 return results