blob: fe8fb8611949605f91df92fcd969e4cc8a4344e1 [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/',
350 '^components/printing/',
351 '^components/proxy_config/',
352 '^components/quirks/',
353 '^components/rappor/',
354 '^components/remote_cocoa/',
355 '^components/renderer_context_menu/',
356 '^components/rlz/',
357 '^components/safe_browsing/',
358 '^components/search_engines/',
359 '^components/search_provider_logos/',
360 '^components/security_interstitials/',
361 '^components/security_state/',
362 '^components/services/',
363 '^components/sessions/',
364 '^components/signin/',
365 '^components/ssl_errors/',
366 '^components/storage_monitor/',
367 '^components/subresource_filter/',
368 '^components/suggestions/',
369 '^components/supervised_user_error_page/',
370 '^components/sync/',
371 '^components/sync_bookmarks/',
372 '^components/sync_device_info/',
373 '^components/sync_preferences/',
374 '^components/sync_sessions/',
375 '^components/test/',
376 '^components/tracing/',
377 '^components/translate/',
378 '^components/ukm/',
379 '^components/update_client/',
380 '^components/upload_list/',
381 '^components/variations/',
382 '^components/visitedlink/',
383 '^components/web_cache/',
384 '^components/web_resource/',
danakj7a2b7082019-05-21 21:13:51385 '^components/webcrypto/',
386 '^components/webdata/',
387 '^components/webdata_services/',
388 '^components/wifi/',
389 '^components/zoom/',
390 '^content/app/',
391 '^content/browser/',
392 '^content/child/',
393 '^content/common/',
394 '^content/public/',
395 '^content/renderer/android/',
396 '^content/renderer/fetchers/',
397 '^content/renderer/image_downloader/',
398 '^content/renderer/input/',
399 '^content/renderer/java/',
400 '^content/renderer/media/',
401 '^content/renderer/media_capture_from_element/',
402 '^content/renderer/media_recorder/',
403 '^content/renderer/p2p/',
404 '^content/renderer/pepper/',
405 '^content/renderer/service_worker/',
406 '^content/renderer/worker/',
407 '^content/test/',
408 '^content/utility/',
409 '^dbus/',
410 '^device/base/',
411 '^device/bluetooth/',
412 '^device/fido/',
413 '^device/gamepad/',
414 '^device/udev_linux/',
415 '^device/vr/',
416 '^extensions/',
417 '^gin/',
418 '^google_apis/dive/',
419 '^google_apis/gaia/',
420 '^google_apis/gcm/',
421 '^headless/',
422 '^ios/chrome/',
423 '^ios/components/',
424 '^ios/net/',
425 '^ios/web/',
426 '^ios/web_view/',
427 '^ipc/',
428 '^media/audio/',
429 '^media/base/',
430 '^media/capture/',
431 '^media/cast/',
432 '^media/cdm/',
433 '^media/device_monitors/',
434 '^media/ffmpeg/',
435 '^media/filters/',
436 '^media/formats/',
437 '^media/gpu/',
438 '^media/mojo/',
439 '^media/muxers/',
440 '^media/remoting/',
441 '^media/renderers/',
442 '^media/test/',
443 '^mojo/core/',
444 '^mojo/public/',
445 '^net/',
446 '^ppapi/proxy/',
447 '^ppapi/shared_impl/',
448 '^ppapi/tests/',
449 '^ppapi/thunk/',
450 '^remoting/base/',
451 '^remoting/client/',
452 '^remoting/codec/',
453 '^remoting/host/',
454 '^remoting/internal/',
455 '^remoting/ios/',
456 '^remoting/protocol/',
457 '^remoting/signaling/',
458 '^remoting/test/',
459 '^sandbox/linux/',
460 '^sandbox/win/',
461 '^services/',
462 '^storage/browser/',
463 '^testing/gmock_mutant.h',
464 '^testing/libfuzzer/',
465 '^third_party/blink/',
466 '^third_party/crashpad/crashpad/test/gtest_main.cc',
467 '^third_party/leveldatabase/leveldb_chrome.cc',
468 '^third_party/boringssl/gtest_main_chromium.cc',
469 '^third_party/cacheinvalidation/overrides/' +
470 'google/cacheinvalidation/deps/callback.h',
471 '^third_party/libaddressinput/chromium/chrome_address_validator.cc',
472 '^third_party/zlib/google/',
473 '^tools/android/',
474 '^tools/clang/base_bind_rewriters/', # Intentional.
475 '^tools/gdb/gdb_chrome.py', # Intentional.
476 '^ui/accelerated_widget_mac/',
477 '^ui/android/',
478 '^ui/aura/',
479 '^ui/base/',
480 '^ui/compositor/',
481 '^ui/display/',
482 '^ui/events/',
483 '^ui/gfx/',
484 '^ui/message_center/',
danakj7a2b7082019-05-21 21:13:51485 '^ui/snapshot/',
486 '^ui/views_content_client/',
487 '^ui/wm/',
488))
[email protected]127f18ec2012-06-16 05:05:59489
Daniel Bratell609102be2019-03-27 20:53:21490# Format: Sequence of tuples containing:
491# * String pattern or, if starting with a slash, a regular expression.
492# * Sequence of strings to show when the pattern matches.
493# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
494# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59495_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20496 (
Dave Tapuska98199b612019-07-10 13:30:44497 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53498 (
499 'New code should not use NULL. Use nullptr instead.',
500 ),
501 True,
502 (),
503 ),
Antonio Gomes07300d02019-03-13 20:59:57504 # Make sure that gtest's FRIEND_TEST() macro is not used; the
505 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
506 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53507 (
[email protected]23e6cbc2012-06-16 18:51:20508 'FRIEND_TEST(',
509 (
[email protected]e3c945502012-06-26 20:01:49510 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20511 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
512 ),
513 False,
[email protected]7345da02012-11-27 14:31:49514 (),
[email protected]23e6cbc2012-06-16 18:51:20515 ),
516 (
Dave Tapuska98199b612019-07-10 13:30:44517 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53518 (
519 'Chrome clients wishing to select events on X windows should use',
520 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
521 'you are selecting events from the GPU process, or if you are using',
522 'an XDisplay other than gfx::GetXDisplay().',
523 ),
524 True,
525 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40526 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04527 r"^ui[\\/]gl[\\/].*\.cc$",
528 r"^media[\\/]gpu[\\/].*\.cc$",
529 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53530 ),
531 ),
532 (
Dave Tapuska98199b612019-07-10 13:30:44533 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20534 (
thomasanderson11aa41dc2017-06-08 22:22:38535 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20536 ),
537 True,
538 (
Egor Paskoce145c42018-09-28 19:31:04539 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
540 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
541 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20542 ),
543 ),
544 (
tomhudsone2c14d552016-05-26 17:07:46545 'setMatrixClip',
546 (
547 'Overriding setMatrixClip() is prohibited; ',
548 'the base function is deprecated. ',
549 ),
550 True,
551 (),
552 ),
553 (
[email protected]52657f62013-05-20 05:30:31554 'SkRefPtr',
555 (
556 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22557 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31558 ),
559 True,
560 (),
561 ),
562 (
563 'SkAutoRef',
564 (
565 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22566 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31567 ),
568 True,
569 (),
570 ),
571 (
572 'SkAutoTUnref',
573 (
574 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22575 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31576 ),
577 True,
578 (),
579 ),
580 (
581 'SkAutoUnref',
582 (
583 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
584 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22585 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31586 ),
587 True,
588 (),
589 ),
[email protected]d89eec82013-12-03 14:10:59590 (
591 r'/HANDLE_EINTR\(.*close',
592 (
593 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
594 'descriptor will be closed, and it is incorrect to retry the close.',
595 'Either call close directly and ignore its return value, or wrap close',
596 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
597 ),
598 True,
599 (),
600 ),
601 (
602 r'/IGNORE_EINTR\((?!.*close)',
603 (
604 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
605 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
606 ),
607 True,
608 (
609 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04610 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
611 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59612 ),
613 ),
[email protected]ec5b3f02014-04-04 18:43:43614 (
615 r'/v8::Extension\(',
616 (
617 'Do not introduce new v8::Extensions into the code base, use',
618 'gin::Wrappable instead. See http://crbug.com/334679',
619 ),
620 True,
[email protected]f55c90ee62014-04-12 00:50:03621 (
Egor Paskoce145c42018-09-28 19:31:04622 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03623 ),
[email protected]ec5b3f02014-04-04 18:43:43624 ),
skyostilf9469f72015-04-20 10:38:52625 (
jame2d1a952016-04-02 00:27:10626 '#pragma comment(lib,',
627 (
628 'Specify libraries to link with in build files and not in the source.',
629 ),
630 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41631 (
tzik3f295992018-12-04 20:32:23632 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04633 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41634 ),
jame2d1a952016-04-02 00:27:10635 ),
fdorayc4ac18d2017-05-01 21:39:59636 (
Gabriel Charette7cc6c432018-04-25 20:52:02637 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59638 (
639 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
640 ),
641 False,
642 (),
643 ),
644 (
Gabriel Charette7cc6c432018-04-25 20:52:02645 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59646 (
647 'Consider using THREAD_CHECKER macros instead of the class directly.',
648 ),
649 False,
650 (),
651 ),
dbeamb6f4fde2017-06-15 04:03:06652 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06653 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
654 (
655 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
656 'deprecated (http://crbug.com/634507). Please avoid converting away',
657 'from the Time types in Chromium code, especially if any math is',
658 'being done on time values. For interfacing with platform/library',
659 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
660 'type converter methods instead. For faking TimeXXX values (for unit',
661 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
662 'other use cases, please contact base/time/OWNERS.',
663 ),
664 False,
665 (),
666 ),
667 (
dbeamb6f4fde2017-06-15 04:03:06668 'CallJavascriptFunctionUnsafe',
669 (
670 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
671 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
672 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
673 ),
674 False,
675 (
Egor Paskoce145c42018-09-28 19:31:04676 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
677 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
678 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06679 ),
680 ),
dskiba1474c2bfd62017-07-20 02:19:24681 (
682 'leveldb::DB::Open',
683 (
684 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
685 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
686 "Chrome's tracing, making their memory usage visible.",
687 ),
688 True,
689 (
690 r'^third_party/leveldatabase/.*\.(cc|h)$',
691 ),
Gabriel Charette0592c3a2017-07-26 12:02:04692 ),
693 (
Chris Mumfordc38afb62017-10-09 17:55:08694 'leveldb::NewMemEnv',
695 (
696 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58697 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
698 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08699 ),
700 True,
701 (
702 r'^third_party/leveldatabase/.*\.(cc|h)$',
703 ),
704 ),
705 (
Gabriel Charetted9839bc2017-07-29 14:17:47706 'RunLoop::QuitCurrent',
707 (
Robert Liao64b7ab22017-08-04 23:03:43708 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
709 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47710 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41711 False,
Gabriel Charetted9839bc2017-07-29 14:17:47712 (),
Gabriel Charettea44975052017-08-21 23:14:04713 ),
714 (
715 'base::ScopedMockTimeMessageLoopTaskRunner',
716 (
Gabriel Charette87cc1af2018-04-25 20:52:51717 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charette21a47f0132019-07-16 16:47:20718 'ScopedTaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51719 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
720 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
721 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04722 ),
Gabriel Charette87cc1af2018-04-25 20:52:51723 False,
Gabriel Charettea44975052017-08-21 23:14:04724 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57725 ),
726 (
Dave Tapuska98199b612019-07-10 13:30:44727 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57728 (
729 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02730 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57731 ),
732 True,
733 (),
Francois Doray43670e32017-09-27 12:40:38734 ),
735 (
Peter Kasting991618a62019-06-17 22:00:09736 r'/\bstd::stoi\b',
737 (
738 'std::stoi uses exceptions to communicate results. ',
739 'Use base::StringToInt() instead.',
740 ),
741 True,
742 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
743 ),
744 (
745 r'/\bstd::stol\b',
746 (
747 'std::stol uses exceptions to communicate results. ',
748 'Use base::StringToInt() instead.',
749 ),
750 True,
751 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
752 ),
753 (
754 r'/\bstd::stoul\b',
755 (
756 'std::stoul uses exceptions to communicate results. ',
757 'Use base::StringToUint() instead.',
758 ),
759 True,
760 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
761 ),
762 (
763 r'/\bstd::stoll\b',
764 (
765 'std::stoll uses exceptions to communicate results. ',
766 'Use base::StringToInt64() instead.',
767 ),
768 True,
769 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
770 ),
771 (
772 r'/\bstd::stoull\b',
773 (
774 'std::stoull uses exceptions to communicate results. ',
775 'Use base::StringToUint64() instead.',
776 ),
777 True,
778 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
779 ),
780 (
781 r'/\bstd::stof\b',
782 (
783 'std::stof uses exceptions to communicate results. ',
784 'For locale-independent values, e.g. reading numbers from disk',
785 'profiles, use base::StringToDouble().',
786 'For user-visible values, parse using ICU.',
787 ),
788 True,
789 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
790 ),
791 (
792 r'/\bstd::stod\b',
793 (
794 'std::stod uses exceptions to communicate results. ',
795 'For locale-independent values, e.g. reading numbers from disk',
796 'profiles, use base::StringToDouble().',
797 'For user-visible values, parse using ICU.',
798 ),
799 True,
800 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
801 ),
802 (
803 r'/\bstd::stold\b',
804 (
805 'std::stold uses exceptions to communicate results. ',
806 'For locale-independent values, e.g. reading numbers from disk',
807 'profiles, use base::StringToDouble().',
808 'For user-visible values, parse using ICU.',
809 ),
810 True,
811 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
812 ),
813 (
Daniel Bratell69334cc2019-03-26 11:07:45814 r'/\bstd::to_string\b',
815 (
816 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09817 'For locale-independent strings, e.g. writing numbers to disk',
818 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45819 'For user-visible strings, use base::FormatNumber() and',
820 'the related functions in base/i18n/number_formatting.h.',
821 ),
Peter Kasting991618a62019-06-17 22:00:09822 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21823 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45824 ),
825 (
826 r'/\bstd::shared_ptr\b',
827 (
828 'std::shared_ptr should not be used. Use scoped_refptr instead.',
829 ),
830 True,
Daniel Bratell609102be2019-03-27 20:53:21831 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
832 ),
833 (
Peter Kasting991618a62019-06-17 22:00:09834 r'/\bstd::weak_ptr\b',
835 (
836 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
837 ),
838 True,
839 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
840 ),
841 (
Daniel Bratell609102be2019-03-27 20:53:21842 r'/\blong long\b',
843 (
844 'long long is banned. Use stdint.h if you need a 64 bit number.',
845 ),
846 False, # Only a warning since it is already used.
847 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
848 ),
849 (
850 r'/\bstd::bind\b',
851 (
852 'std::bind is banned because of lifetime risks.',
853 'Use base::BindOnce or base::BindRepeating instead.',
854 ),
855 True,
856 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
857 ),
858 (
859 r'/\b#include <chrono>\b',
860 (
861 '<chrono> overlaps with Time APIs in base. Keep using',
862 'base classes.',
863 ),
864 True,
865 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
866 ),
867 (
868 r'/\b#include <exception>\b',
869 (
870 'Exceptions are banned and disabled in Chromium.',
871 ),
872 True,
873 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
874 ),
875 (
876 r'/\bstd::function\b',
877 (
878 'std::function is banned. Instead use base::Callback which directly',
879 'supports Chromium\'s weak pointers, ref counting and more.',
880 ),
Peter Kasting991618a62019-06-17 22:00:09881 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21882 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
883 ),
884 (
885 r'/\b#include <random>\b',
886 (
887 'Do not use any random number engines from <random>. Instead',
888 'use base::RandomBitGenerator.',
889 ),
890 True,
891 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
892 ),
893 (
894 r'/\bstd::ratio\b',
895 (
896 'std::ratio is banned by the Google Style Guide.',
897 ),
898 True,
899 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45900 ),
901 (
Francois Doray43670e32017-09-27 12:40:38902 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
903 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
904 (
905 'Use the new API in base/threading/thread_restrictions.h.',
906 ),
Gabriel Charette04b138f2018-08-06 00:03:22907 False,
Francois Doray43670e32017-09-27 12:40:38908 (),
909 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38910 (
danakj7a2b7082019-05-21 21:13:51911 r'/\bbase::Bind\(',
912 (
913 'Please use base::Bind{Once,Repeating} instead',
914 'of base::Bind. (crbug.com/714018)',
915 ),
916 False,
917 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
918 ),
919 (
920 r'/\bbase::Callback[<:]',
921 (
922 'Please use base::{Once,Repeating}Callback instead',
923 'of base::Callback. (crbug.com/714018)',
924 ),
925 False,
926 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
927 ),
928 (
929 r'/\bbase::Closure\b',
930 (
931 'Please use base::{Once,Repeating}Closure instead',
932 'of base::Closure. (crbug.com/714018)',
933 ),
934 False,
935 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
936 ),
937 (
Alex Ilin5929abe32019-04-03 17:09:34938 r'/base::SharedMemory(|Handle)',
Alex Ilin63058f62019-03-28 19:29:45939 (
940 'base::SharedMemory is deprecated. Please use',
941 '{Writable,ReadOnly}SharedMemoryRegion instead.',
942 ),
943 False,
944 (),
945 ),
946 (
Michael Giuffrida7f93d6922019-04-19 14:39:58947 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19948 (
949 'RunMessageLoop is deprecated, use RunLoop instead.',
950 ),
951 False,
952 (),
953 ),
954 (
Dave Tapuska98199b612019-07-10 13:30:44955 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19956 (
957 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
958 ),
959 False,
960 (),
961 ),
962 (
Dave Tapuska98199b612019-07-10 13:30:44963 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19964 (
965 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
966 "if you're convinced you need this.",
967 ),
968 False,
969 (),
970 ),
971 (
Dave Tapuska98199b612019-07-10 13:30:44972 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19973 (
974 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
975 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
976 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
977 'async events instead of flushing threads.',
978 ),
979 False,
980 (),
981 ),
982 (
983 r'MessageLoopRunner',
984 (
985 'MessageLoopRunner is deprecated, use RunLoop instead.',
986 ),
987 False,
988 (),
989 ),
990 (
Dave Tapuska98199b612019-07-10 13:30:44991 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19992 (
993 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
994 "gab@ if you found a use case where this is the only solution.",
995 ),
996 False,
997 (),
998 ),
999 (
Victor Costane48a2e82019-03-15 22:02:341000 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161001 (
Victor Costane48a2e82019-03-15 22:02:341002 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161003 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1004 ),
1005 True,
1006 (
1007 r'^sql/initialization\.(cc|h)$',
1008 r'^third_party/sqlite/.*\.(c|cc|h)$',
1009 ),
1010 ),
Matt Menke7f520a82018-03-28 21:38:371011 (
1012 'net::URLFetcher',
1013 (
1014 'net::URLFetcher should no longer be used in content embedders. ',
1015 'Instead, use network::SimpleURLLoader instead, which supports ',
1016 'an out-of-process network stack. ',
1017 'net::URLFetcher may still be used in binaries that do not embed',
1018 'content.',
1019 ),
Matt Menke59716d02018-04-05 12:45:531020 False,
Matt Menke7f520a82018-03-28 21:38:371021 (
Egor Paskoce145c42018-09-28 19:31:041022 r'^ios[\\/].*\.(cc|h)$',
1023 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:371024 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:041025 r'^net[\\/].*\.(cc|h)$',
1026 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi347f6992019-07-11 00:29:201027 r'^fuchsia/engine/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:371028 ),
1029 ),
jdoerried7d10ab2018-04-27 10:46:131030 (
Dave Tapuska98199b612019-07-10 13:30:441031 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471032 (
1033 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1034 'base::RandomShuffle instead.'
1035 ),
1036 True,
1037 (),
1038 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241039 (
1040 'ios/web/public/test/http_server',
1041 (
1042 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1043 ),
1044 False,
1045 (),
1046 ),
Robert Liao764c9492019-01-24 18:46:281047 (
1048 'GetAddressOf',
1049 (
1050 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
1051 'implicated in a few leaks. Use operator& instead.'
1052 ),
1053 True,
1054 (),
1055 ),
Antonio Gomes07300d02019-03-13 20:59:571056 (
1057 'DEFINE_TYPE_CASTS',
1058 (
1059 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1060 '//third_party/blink/renderer/platform/casting.h.'
1061 ),
1062 True,
1063 (
1064 r'^third_party/blink/renderer/.*\.(cc|h)$',
1065 ),
1066 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381067 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371068 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381069 (
1070 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1071 ),
1072 True,
1073 (),
1074 ),
Ben Lewisa9514602019-04-29 17:53:051075 (
1076 'SHFileOperation',
1077 (
1078 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1079 'complex functions to achieve the same goals. Use IFileOperation for ',
1080 'any esoteric actions instead.'
1081 ),
1082 True,
1083 (),
1084 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181085 (
Cliff Smolinsky81951642019-04-30 21:39:511086 'StringFromGUID2',
1087 (
1088 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1089 'Use base::win::String16FromGUID instead.'
1090 ),
1091 True,
1092 (
1093 r'/base/win/win_util_unittest.cc'
1094 ),
1095 ),
1096 (
1097 'StringFromCLSID',
1098 (
1099 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1100 'Use base::win::String16FromGUID instead.'
1101 ),
1102 True,
1103 (
1104 r'/base/win/win_util_unittest.cc'
1105 ),
1106 ),
1107 (
Avi Drissman7382afa02019-04-29 23:27:131108 'kCFAllocatorNull',
1109 (
1110 'The use of kCFAllocatorNull with the NoCopy creation of ',
1111 'CoreFoundation types is prohibited.',
1112 ),
1113 True,
1114 (),
1115 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291116 (
1117 'mojo::ConvertTo',
1118 (
1119 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1120 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1121 'StringTraits if you would like to convert between custom types and',
1122 'the wire format of mojom types.'
1123 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221124 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291125 (
1126 r'^third_party/blink/.*\.(cc|h)$',
1127 r'^content/renderer/.*\.(cc|h)$',
1128 ),
1129 ),
[email protected]127f18ec2012-06-16 05:05:591130)
1131
wnwenbdc444e2016-05-25 13:44:151132
mlamouria82272622014-09-16 18:45:041133_IPC_ENUM_TRAITS_DEPRECATED = (
1134 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501135 'See http://www.chromium.org/Home/chromium-security/education/'
1136 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041137
Stephen Martinis97a394142018-06-07 23:06:051138_LONG_PATH_ERROR = (
1139 'Some files included in this CL have file names that are too long (> 200'
1140 ' characters). If committed, these files will cause issues on Windows. See'
1141 ' https://crbug.com/612667 for more details.'
1142)
1143
Shenghua Zhangbfaa38b82017-11-16 21:58:021144_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041145 r".*[\\/]BuildHooksAndroidImpl\.java",
1146 r".*[\\/]LicenseContentProvider\.java",
1147 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281148 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021149]
[email protected]127f18ec2012-06-16 05:05:591150
Sean Kau46e29bc2017-08-28 16:31:161151# These paths contain test data and other known invalid JSON files.
1152_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041153 r'test[\\/]data[\\/]',
1154 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1155 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041156 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431157 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161158]
1159
1160
[email protected]b00342e7f2013-03-26 16:21:541161_VALID_OS_MACROS = (
1162 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081163 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541164 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121165 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541166 'OS_BSD',
1167 'OS_CAT', # For testing.
1168 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041169 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541170 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371171 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541172 'OS_IOS',
1173 'OS_LINUX',
1174 'OS_MACOSX',
1175 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211176 'OS_NACL_NONSFI',
1177 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121178 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541179 'OS_OPENBSD',
1180 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371181 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541182 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541183 'OS_WIN',
1184)
1185
1186
agrievef32bcc72016-04-04 14:57:401187_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391188 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361189 'base/android/jni_generator/jni_generator.pydeps',
1190 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221191 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361192 'build/android/gyp/aar.pydeps',
1193 'build/android/gyp/aidl.pydeps',
1194 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381195 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361196 'build/android/gyp/bytecode_processor.pydeps',
1197 'build/android/gyp/compile_resources.pydeps',
Andrew Grievef89e926c2019-02-07 18:36:571198 'build/android/gyp/create_app_bundle_minimal_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361199 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1200 'build/android/gyp/copy_ex.pydeps',
1201 'build/android/gyp/create_app_bundle.pydeps',
1202 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361203 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221204 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361205 'build/android/gyp/create_tool_wrapper.pydeps',
1206 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591207 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361208 'build/android/gyp/dex.pydeps',
1209 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361210 'build/android/gyp/filter_zip.pydeps',
1211 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361212 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361213 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581214 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361215 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261216 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361217 'build/android/gyp/javac.pydeps',
1218 'build/android/gyp/jinja_template.pydeps',
1219 'build/android/gyp/lint.pydeps',
1220 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361221 'build/android/gyp/merge_manifest.pydeps',
1222 'build/android/gyp/prepare_resources.pydeps',
1223 'build/android/gyp/proguard.pydeps',
1224 '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',
John Budorickbc3571aa2019-04-25 02:20:061242 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221243 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401244]
1245
wnwenbdc444e2016-05-25 13:44:151246
agrievef32bcc72016-04-04 14:57:401247_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1248
1249
Eric Boren6fd2b932018-01-25 15:05:081250# Bypass the AUTHORS check for these accounts.
1251_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291252 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1253 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081254 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321255 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591256 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451257 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591258 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221259 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041260 ) | set('%[email protected]' % s
1261 for s in ('chromium-autoroll',)
1262 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301263 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081264
1265
Daniel Bratell65b033262019-04-23 08:17:061266def _IsCPlusPlusFile(input_api, file_path):
1267 """Returns True if this file contains C++-like code (and not Python,
1268 Go, Java, MarkDown, ...)"""
1269
1270 ext = input_api.os_path.splitext(file_path)[1]
1271 # This list is compatible with CppChecker.IsCppFile but we should
1272 # consider adding ".c" to it. If we do that we can use this function
1273 # at more places in the code.
1274 return ext in (
1275 '.h',
1276 '.cc',
1277 '.cpp',
1278 '.m',
1279 '.mm',
1280 )
1281
1282def _IsCPlusPlusHeaderFile(input_api, file_path):
1283 return input_api.os_path.splitext(file_path)[1] == ".h"
1284
1285
1286def _IsJavaFile(input_api, file_path):
1287 return input_api.os_path.splitext(file_path)[1] == ".java"
1288
1289
1290def _IsProtoFile(input_api, file_path):
1291 return input_api.os_path.splitext(file_path)[1] == ".proto"
1292
[email protected]55459852011-08-10 15:17:191293def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1294 """Attempts to prevent use of functions intended only for testing in
1295 non-testing code. For now this is just a best-effort implementation
1296 that ignores header files and may have some false positives. A
1297 better implementation would probably need a proper C++ parser.
1298 """
1299 # We only scan .cc files and the like, as the declaration of
1300 # for-testing functions in header files are hard to distinguish from
1301 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491302 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191303
jochenc0d4808c2015-07-27 09:25:421304 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191305 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091306 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191307 exclusion_pattern = input_api.re.compile(
1308 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1309 base_function_pattern, base_function_pattern))
1310
1311 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441312 black_list = (_EXCLUDED_PATHS +
1313 _TEST_CODE_EXCLUDED_PATHS +
1314 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191315 return input_api.FilterSourceFile(
1316 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491317 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191318 black_list=black_list)
1319
1320 problems = []
1321 for f in input_api.AffectedSourceFiles(FilterFile):
1322 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241323 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031324 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461325 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031326 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191327 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031328 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191329
1330 if problems:
[email protected]f7051d52013-04-02 18:31:421331 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031332 else:
1333 return []
[email protected]55459852011-08-10 15:17:191334
1335
Vaclav Brozek7dbc28c2018-03-27 08:35:231336def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1337 """This is a simplified version of
1338 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1339 """
1340 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1341 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1342 name_pattern = r'ForTest(s|ing)?'
1343 # Describes an occurrence of "ForTest*" inside a // comment.
1344 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1345 # Catch calls.
1346 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1347 # Ignore definitions. (Comments are ignored separately.)
1348 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1349
1350 problems = []
1351 sources = lambda x: input_api.FilterSourceFile(
1352 x,
1353 black_list=(('(?i).*test', r'.*\/junit\/')
1354 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491355 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231356 )
1357 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1358 local_path = f.LocalPath()
1359 is_inside_javadoc = False
1360 for line_number, line in f.ChangedContents():
1361 if is_inside_javadoc and javadoc_end_re.search(line):
1362 is_inside_javadoc = False
1363 if not is_inside_javadoc and javadoc_start_re.search(line):
1364 is_inside_javadoc = True
1365 if is_inside_javadoc:
1366 continue
1367 if (inclusion_re.search(line) and
1368 not comment_re.search(line) and
1369 not exclusion_re.search(line)):
1370 problems.append(
1371 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1372
1373 if problems:
1374 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1375 else:
1376 return []
1377
1378
[email protected]10689ca2011-09-02 02:31:541379def _CheckNoIOStreamInHeaders(input_api, output_api):
1380 """Checks to make sure no .h files include <iostream>."""
1381 files = []
1382 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1383 input_api.re.MULTILINE)
1384 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1385 if not f.LocalPath().endswith('.h'):
1386 continue
1387 contents = input_api.ReadFile(f)
1388 if pattern.search(contents):
1389 files.append(f)
1390
1391 if len(files):
yolandyandaabc6d2016-04-18 18:29:391392 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061393 'Do not #include <iostream> in header files, since it inserts static '
1394 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541395 '#include <ostream>. See http://crbug.com/94794',
1396 files) ]
1397 return []
1398
Danil Chapovalov3518f362018-08-11 16:13:431399def _CheckNoStrCatRedefines(input_api, output_api):
1400 """Checks no windows headers with StrCat redefined are included directly."""
1401 files = []
1402 pattern_deny = input_api.re.compile(
1403 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1404 input_api.re.MULTILINE)
1405 pattern_allow = input_api.re.compile(
1406 r'^#include\s"base/win/windows_defines.inc"',
1407 input_api.re.MULTILINE)
1408 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1409 contents = input_api.ReadFile(f)
1410 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1411 files.append(f.LocalPath())
1412
1413 if len(files):
1414 return [output_api.PresubmitError(
1415 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1416 'directly since they pollute code with StrCat macro. Instead, '
1417 'include matching header from base/win. See http://crbug.com/856536',
1418 files) ]
1419 return []
1420
[email protected]10689ca2011-09-02 02:31:541421
[email protected]72df4e782012-06-21 16:28:181422def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521423 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181424 problems = []
1425 for f in input_api.AffectedFiles():
1426 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1427 continue
1428
1429 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041430 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181431 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1432
1433 if not problems:
1434 return []
1435 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1436 '\n'.join(problems))]
1437
Dominic Battre033531052018-09-24 15:45:341438def _CheckNoDISABLETypoInTests(input_api, output_api):
1439 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1440
1441 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1442 instead of DISABLED_. To filter false positives, reports are only generated
1443 if a corresponding MAYBE_ line exists.
1444 """
1445 problems = []
1446
1447 # The following two patterns are looked for in tandem - is a test labeled
1448 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1449 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1450 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1451
1452 # This is for the case that a test is disabled on all platforms.
1453 full_disable_pattern = input_api.re.compile(
1454 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1455 input_api.re.MULTILINE)
1456
Katie Df13948e2018-09-25 07:33:441457 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341458 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1459 continue
1460
1461 # Search for MABYE_, DISABLE_ pairs.
1462 disable_lines = {} # Maps of test name to line number.
1463 maybe_lines = {}
1464 for line_num, line in f.ChangedContents():
1465 disable_match = disable_pattern.search(line)
1466 if disable_match:
1467 disable_lines[disable_match.group(1)] = line_num
1468 maybe_match = maybe_pattern.search(line)
1469 if maybe_match:
1470 maybe_lines[maybe_match.group(1)] = line_num
1471
1472 # Search for DISABLE_ occurrences within a TEST() macro.
1473 disable_tests = set(disable_lines.keys())
1474 maybe_tests = set(maybe_lines.keys())
1475 for test in disable_tests.intersection(maybe_tests):
1476 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1477
1478 contents = input_api.ReadFile(f)
1479 full_disable_match = full_disable_pattern.search(contents)
1480 if full_disable_match:
1481 problems.append(' %s' % f.LocalPath())
1482
1483 if not problems:
1484 return []
1485 return [
1486 output_api.PresubmitPromptWarning(
1487 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1488 '\n'.join(problems))
1489 ]
1490
[email protected]72df4e782012-06-21 16:28:181491
danakj61c1aa22015-10-26 19:55:521492def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571493 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521494 errors = []
1495 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1496 input_api.re.MULTILINE)
1497 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1498 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1499 continue
1500 for lnum, line in f.ChangedContents():
1501 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171502 errors.append(output_api.PresubmitError(
1503 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571504 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171505 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521506 return errors
1507
1508
Makoto Shimazu3ad422cd2019-05-08 02:35:141509def _FindHistogramNameInChunk(histogram_name, chunk):
1510 """Tries to find a histogram name or prefix in a line.
1511
1512 Returns the existence of the histogram name, or None if it needs more chunk
1513 to determine."""
mcasasb7440c282015-02-04 14:52:191514 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1515 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141516 if '<affected-histogram' in chunk:
1517 # If the tag is not completed, needs more chunk to get the name.
1518 if not '>' in chunk:
1519 return None
1520 if not 'name="' in chunk:
1521 return False
1522 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1523 # expect the only attribute is the name.
1524 histogram_prefix = chunk.split('"')[1]
1525 return histogram_prefix in histogram_name
1526 # Typically the whole histogram name should in the line.
1527 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191528
1529
1530def _CheckUmaHistogramChanges(input_api, output_api):
1531 """Check that UMA histogram names in touched lines can still be found in other
1532 lines of the patch or in histograms.xml. Note that this check would not catch
1533 the reverse: changes in histograms.xml not matched in the code itself."""
1534 touched_histograms = []
1535 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471536 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1537 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1538 name_pattern = r'"(.*?)"'
1539 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1540 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1541 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1542 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1543 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171544 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191545 for f in input_api.AffectedFiles():
1546 # If histograms.xml itself is modified, keep the modified lines for later.
1547 if f.LocalPath().endswith(('histograms.xml')):
1548 histograms_xml_modifications = f.ChangedContents()
1549 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471550 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1551 single_line_re = single_line_c_re
1552 split_line_prefix_re = split_line_c_prefix_re
1553 elif f.LocalPath().endswith(('java')):
1554 single_line_re = single_line_java_re
1555 split_line_prefix_re = split_line_java_prefix_re
1556 else:
mcasasb7440c282015-02-04 14:52:191557 continue
1558 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171559 if last_line_matched_prefix:
1560 suffix_found = split_line_suffix_re.search(line)
1561 if suffix_found :
1562 touched_histograms.append([suffix_found.group(1), f, line_num])
1563 last_line_matched_prefix = False
1564 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061565 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191566 if found:
1567 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171568 continue
1569 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191570
1571 # Search for the touched histogram names in the local modifications to
1572 # histograms.xml, and, if not found, on the base histograms.xml file.
1573 unmatched_histograms = []
1574 for histogram_info in touched_histograms:
1575 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141576 chunk = ''
mcasasb7440c282015-02-04 14:52:191577 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141578 chunk += line
1579 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1580 if histogram_name_found is None:
1581 continue
1582 chunk = ''
mcasasb7440c282015-02-04 14:52:191583 if histogram_name_found:
1584 break
1585 if not histogram_name_found:
1586 unmatched_histograms.append(histogram_info)
1587
eromanb90c82e7e32015-04-01 15:13:491588 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191589 problems = []
1590 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491591 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191592 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451593 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191594 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141595 chunk = ''
mcasasb7440c282015-02-04 14:52:191596 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141597 chunk += line
1598 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1599 chunk)
1600 if histogram_name_found is None:
1601 continue
1602 chunk = ''
mcasasb7440c282015-02-04 14:52:191603 if histogram_name_found:
1604 break
1605 if not histogram_name_found:
1606 problems.append(' [%s:%d] %s' %
1607 (f.LocalPath(), line_num, histogram_name))
1608
1609 if not problems:
1610 return []
1611 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1612 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491613 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191614
wnwenbdc444e2016-05-25 13:44:151615
yolandyandaabc6d2016-04-18 18:29:391616def _CheckFlakyTestUsage(input_api, output_api):
1617 """Check that FlakyTest annotation is our own instead of the android one"""
1618 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1619 files = []
1620 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1621 if f.LocalPath().endswith('Test.java'):
1622 if pattern.search(input_api.ReadFile(f)):
1623 files.append(f)
1624 if len(files):
1625 return [output_api.PresubmitError(
1626 'Use org.chromium.base.test.util.FlakyTest instead of '
1627 'android.test.FlakyTest',
1628 files)]
1629 return []
mcasasb7440c282015-02-04 14:52:191630
wnwenbdc444e2016-05-25 13:44:151631
[email protected]8ea5d4b2011-09-13 21:49:221632def _CheckNoNewWStrings(input_api, output_api):
1633 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271634 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221635 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201636 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571637 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341638 '/win/' in f.LocalPath() or
1639 'chrome_elf' in f.LocalPath() or
1640 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201641 continue
[email protected]8ea5d4b2011-09-13 21:49:221642
[email protected]a11dbe9b2012-08-07 01:32:581643 allowWString = False
[email protected]b5c24292011-11-28 14:38:201644 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581645 if 'presubmit: allow wstring' in line:
1646 allowWString = True
1647 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271648 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581649 allowWString = False
1650 else:
1651 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221652
[email protected]55463aa62011-10-12 00:48:271653 if not problems:
1654 return []
1655 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581656 ' If you are calling a cross-platform API that accepts a wstring, '
1657 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271658 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221659
1660
[email protected]2a8ac9c2011-10-19 17:20:441661def _CheckNoDEPSGIT(input_api, output_api):
1662 """Make sure .DEPS.git is never modified manually."""
1663 if any(f.LocalPath().endswith('.DEPS.git') for f in
1664 input_api.AffectedFiles()):
1665 return [output_api.PresubmitError(
1666 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1667 'automated system based on what\'s in DEPS and your changes will be\n'
1668 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501669 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1670 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441671 'for more information')]
1672 return []
1673
1674
tandriief664692014-09-23 14:51:471675def _CheckValidHostsInDEPS(input_api, output_api):
1676 """Checks that DEPS file deps are from allowed_hosts."""
1677 # Run only if DEPS file has been modified to annoy fewer bystanders.
1678 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1679 return []
1680 # Outsource work to gclient verify
1681 try:
John Budorickf20c0042019-04-25 23:23:401682 gclient_path = input_api.os_path.join(
1683 input_api.PresubmitLocalPath(),
1684 'third_party', 'depot_tools', 'gclient.py')
1685 input_api.subprocess.check_output(
1686 [input_api.python_executable, gclient_path, 'verify'],
1687 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471688 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201689 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471690 return [output_api.PresubmitError(
1691 'DEPS file must have only git dependencies.',
1692 long_text=error.output)]
1693
1694
[email protected]127f18ec2012-06-16 05:05:591695def _CheckNoBannedFunctions(input_api, output_api):
1696 """Make sure that banned functions are not used."""
1697 warnings = []
1698 errors = []
1699
wnwenbdc444e2016-05-25 13:44:151700 def IsBlacklisted(affected_file, blacklist):
1701 local_path = affected_file.LocalPath()
1702 for item in blacklist:
1703 if input_api.re.match(item, local_path):
1704 return True
1705 return False
1706
Peter K. Lee6c03ccff2019-07-15 14:40:051707 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541708 local_path = affected_file.LocalPath()
1709 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1710 return False
1711 basename = input_api.os_path.basename(local_path)
1712 if 'ios' in basename.split('_'):
1713 return True
1714 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1715 if sep and 'ios' in local_path.split(sep):
1716 return True
1717 return False
1718
wnwenbdc444e2016-05-25 13:44:151719 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
1720 matched = False
1721 if func_name[0:1] == '/':
1722 regex = func_name[1:]
1723 if input_api.re.search(regex, line):
1724 matched = True
1725 elif func_name in line:
dchenge07de812016-06-20 19:27:171726 matched = True
wnwenbdc444e2016-05-25 13:44:151727 if matched:
dchenge07de812016-06-20 19:27:171728 problems = warnings
wnwenbdc444e2016-05-25 13:44:151729 if error:
dchenge07de812016-06-20 19:27:171730 problems = errors
wnwenbdc444e2016-05-25 13:44:151731 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
1732 for message_line in message:
1733 problems.append(' %s' % message_line)
1734
Eric Stevensona9a980972017-09-23 00:04:411735 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1736 for f in input_api.AffectedFiles(file_filter=file_filter):
1737 for line_num, line in f.ChangedContents():
1738 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1739 CheckForMatch(f, line_num, line, func_name, message, error)
1740
[email protected]127f18ec2012-06-16 05:05:591741 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1742 for f in input_api.AffectedFiles(file_filter=file_filter):
1743 for line_num, line in f.ChangedContents():
1744 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151745 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591746
Peter K. Lee6c03ccff2019-07-15 14:40:051747 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541748 for line_num, line in f.ChangedContents():
1749 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1750 CheckForMatch(f, line_num, line, func_name, message, error)
1751
Peter K. Lee6c03ccff2019-07-15 14:40:051752 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1753 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1754 for line_num, line in f.ChangedContents():
1755 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1756 CheckForMatch(f, line_num, line, func_name, message, error)
1757
[email protected]127f18ec2012-06-16 05:05:591758 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1759 for f in input_api.AffectedFiles(file_filter=file_filter):
1760 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491761 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491762 if IsBlacklisted(f, excluded_paths):
1763 continue
wnwenbdc444e2016-05-25 13:44:151764 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591765
1766 result = []
1767 if (warnings):
1768 result.append(output_api.PresubmitPromptWarning(
1769 'Banned functions were used.\n' + '\n'.join(warnings)))
1770 if (errors):
1771 result.append(output_api.PresubmitError(
1772 'Banned functions were used.\n' + '\n'.join(errors)))
1773 return result
1774
1775
[email protected]6c063c62012-07-11 19:11:061776def _CheckNoPragmaOnce(input_api, output_api):
1777 """Make sure that banned functions are not used."""
1778 files = []
1779 pattern = input_api.re.compile(r'^#pragma\s+once',
1780 input_api.re.MULTILINE)
1781 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1782 if not f.LocalPath().endswith('.h'):
1783 continue
1784 contents = input_api.ReadFile(f)
1785 if pattern.search(contents):
1786 files.append(f)
1787
1788 if files:
1789 return [output_api.PresubmitError(
1790 'Do not use #pragma once in header files.\n'
1791 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1792 files)]
1793 return []
1794
[email protected]127f18ec2012-06-16 05:05:591795
[email protected]e7479052012-09-19 00:26:121796def _CheckNoTrinaryTrueFalse(input_api, output_api):
1797 """Checks to make sure we don't introduce use of foo ? true : false."""
1798 problems = []
1799 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1800 for f in input_api.AffectedFiles():
1801 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1802 continue
1803
1804 for line_num, line in f.ChangedContents():
1805 if pattern.match(line):
1806 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1807
1808 if not problems:
1809 return []
1810 return [output_api.PresubmitPromptWarning(
1811 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1812 '\n'.join(problems))]
1813
1814
[email protected]55f9f382012-07-31 11:02:181815def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281816 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181817 change. Breaking - rules is an error, breaking ! rules is a
1818 warning.
1819 """
mohan.reddyf21db962014-10-16 12:26:471820 import sys
[email protected]55f9f382012-07-31 11:02:181821 # We need to wait until we have an input_api object and use this
1822 # roundabout construct to import checkdeps because this file is
1823 # eval-ed and thus doesn't have __file__.
1824 original_sys_path = sys.path
1825 try:
1826 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471827 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181828 import checkdeps
[email protected]55f9f382012-07-31 11:02:181829 from rules import Rule
1830 finally:
1831 # Restore sys.path to what it was before.
1832 sys.path = original_sys_path
1833
1834 added_includes = []
rhalavati08acd232017-04-03 07:23:281835 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241836 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181837 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:061838 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501839 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081840 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061841 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501842 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081843 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061844 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501845 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081846 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181847
[email protected]26385172013-05-09 23:11:351848 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181849
1850 error_descriptions = []
1851 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281852 error_subjects = set()
1853 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181854 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1855 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081856 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181857 description_with_path = '%s\n %s' % (path, rule_description)
1858 if rule_type == Rule.DISALLOW:
1859 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281860 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181861 else:
1862 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281863 warning_subjects.add("#includes")
1864
1865 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1866 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081867 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281868 description_with_path = '%s\n %s' % (path, rule_description)
1869 if rule_type == Rule.DISALLOW:
1870 error_descriptions.append(description_with_path)
1871 error_subjects.add("imports")
1872 else:
1873 warning_descriptions.append(description_with_path)
1874 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181875
Jinsuk Kim5a092672017-10-24 22:42:241876 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021877 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081878 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241879 description_with_path = '%s\n %s' % (path, rule_description)
1880 if rule_type == Rule.DISALLOW:
1881 error_descriptions.append(description_with_path)
1882 error_subjects.add("imports")
1883 else:
1884 warning_descriptions.append(description_with_path)
1885 warning_subjects.add("imports")
1886
[email protected]55f9f382012-07-31 11:02:181887 results = []
1888 if error_descriptions:
1889 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281890 'You added one or more %s that violate checkdeps rules.'
1891 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181892 error_descriptions))
1893 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421894 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281895 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181896 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281897 '%s? See relevant DEPS file(s) for details and contacts.' %
1898 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181899 warning_descriptions))
1900 return results
1901
1902
[email protected]fbcafe5a2012-08-08 15:31:221903def _CheckFilePermissions(input_api, output_api):
1904 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151905 if input_api.platform == 'win32':
1906 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291907 checkperms_tool = input_api.os_path.join(
1908 input_api.PresubmitLocalPath(),
1909 'tools', 'checkperms', 'checkperms.py')
1910 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471911 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391912 with input_api.CreateTemporaryFile() as file_list:
1913 for f in input_api.AffectedFiles():
1914 # checkperms.py file/directory arguments must be relative to the
1915 # repository.
1916 file_list.write(f.LocalPath() + '\n')
1917 file_list.close()
1918 args += ['--file-list', file_list.name]
1919 try:
1920 input_api.subprocess.check_output(args)
1921 return []
1922 except input_api.subprocess.CalledProcessError as error:
1923 return [output_api.PresubmitError(
1924 'checkperms.py failed:',
1925 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221926
1927
robertocn832f5992017-01-04 19:01:301928def _CheckTeamTags(input_api, output_api):
1929 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1930 checkteamtags_tool = input_api.os_path.join(
1931 input_api.PresubmitLocalPath(),
1932 'tools', 'checkteamtags', 'checkteamtags.py')
1933 args = [input_api.python_executable, checkteamtags_tool,
1934 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221935 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301936 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1937 'OWNERS']
1938 try:
1939 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:051940 warnings = input_api.subprocess.check_output(args + files).splitlines()
1941 if warnings:
1942 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:301943 return []
1944 except input_api.subprocess.CalledProcessError as error:
1945 return [output_api.PresubmitError(
1946 'checkteamtags.py failed:',
1947 long_text=error.output)]
1948
1949
[email protected]c8278b32012-10-30 20:35:491950def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1951 """Makes sure we don't include ui/aura/window_property.h
1952 in header files.
1953 """
1954 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1955 errors = []
1956 for f in input_api.AffectedFiles():
1957 if not f.LocalPath().endswith('.h'):
1958 continue
1959 for line_num, line in f.ChangedContents():
1960 if pattern.match(line):
1961 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1962
1963 results = []
1964 if errors:
1965 results.append(output_api.PresubmitError(
1966 'Header files should not include ui/aura/window_property.h', errors))
1967 return results
1968
1969
[email protected]70ca77752012-11-20 03:45:031970def _CheckForVersionControlConflictsInFile(input_api, f):
1971 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1972 errors = []
1973 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:161974 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:231975 # First-level headers in markdown look a lot like version control
1976 # conflict markers. http://daringfireball.net/projects/markdown/basics
1977 continue
[email protected]70ca77752012-11-20 03:45:031978 if pattern.match(line):
1979 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1980 return errors
1981
1982
1983def _CheckForVersionControlConflicts(input_api, output_api):
1984 """Usually this is not intentional and will cause a compile failure."""
1985 errors = []
1986 for f in input_api.AffectedFiles():
1987 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1988
1989 results = []
1990 if errors:
1991 results.append(output_api.PresubmitError(
1992 'Version control conflict markers found, please resolve.', errors))
1993 return results
1994
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201995
estadee17314a02017-01-12 16:22:161996def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1997 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1998 errors = []
1999 for f in input_api.AffectedFiles():
2000 for line_num, line in f.ChangedContents():
2001 if pattern.search(line):
2002 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2003
2004 results = []
2005 if errors:
2006 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502007 'Found Google support URL addressed by answer number. Please replace '
2008 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162009 return results
2010
[email protected]70ca77752012-11-20 03:45:032011
[email protected]06e6d0ff2012-12-11 01:36:442012def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2013 def FilterFile(affected_file):
2014 """Filter function for use with input_api.AffectedSourceFiles,
2015 below. This filters out everything except non-test files from
2016 top-level directories that generally speaking should not hard-code
2017 service URLs (e.g. src/android_webview/, src/content/ and others).
2018 """
2019 return input_api.FilterSourceFile(
2020 affected_file,
Egor Paskoce145c42018-09-28 19:31:042021 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442022 black_list=(_EXCLUDED_PATHS +
2023 _TEST_CODE_EXCLUDED_PATHS +
2024 input_api.DEFAULT_BLACK_LIST))
2025
reillyi38965732015-11-16 18:27:332026 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2027 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462028 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2029 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442030 problems = [] # items are (filename, line_number, line)
2031 for f in input_api.AffectedSourceFiles(FilterFile):
2032 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462033 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442034 problems.append((f.LocalPath(), line_num, line))
2035
2036 if problems:
[email protected]f7051d52013-04-02 18:31:422037 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442038 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582039 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442040 [' %s:%d: %s' % (
2041 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032042 else:
2043 return []
[email protected]06e6d0ff2012-12-11 01:36:442044
2045
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492046# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272047def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2048 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312049 The native_client_sdk directory is excluded because it has auto-generated PNG
2050 files for documentation.
[email protected]d2530012013-01-25 16:39:272051 """
[email protected]d2530012013-01-25 16:39:272052 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492053 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042054 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312055 file_filter = lambda f: input_api.FilterSourceFile(
2056 f, white_list=white_list, black_list=black_list)
2057 for f in input_api.AffectedFiles(include_deletes=False,
2058 file_filter=file_filter):
2059 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272060
2061 results = []
2062 if errors:
2063 results.append(output_api.PresubmitError(
2064 'The name of PNG files should not have abbreviations. \n'
2065 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2066 'Contact [email protected] if you have questions.', errors))
2067 return results
2068
2069
Daniel Cheng4dcdb6b2017-04-13 08:30:172070def _ExtractAddRulesFromParsedDeps(parsed_deps):
2071 """Extract the rules that add dependencies from a parsed DEPS file.
2072
2073 Args:
2074 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2075 add_rules = set()
2076 add_rules.update([
2077 rule[1:] for rule in parsed_deps.get('include_rules', [])
2078 if rule.startswith('+') or rule.startswith('!')
2079 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502080 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172081 {}).iteritems():
2082 add_rules.update([
2083 rule[1:] for rule in rules
2084 if rule.startswith('+') or rule.startswith('!')
2085 ])
2086 return add_rules
2087
2088
2089def _ParseDeps(contents):
2090 """Simple helper for parsing DEPS files."""
2091 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172092 class _VarImpl:
2093
2094 def __init__(self, local_scope):
2095 self._local_scope = local_scope
2096
2097 def Lookup(self, var_name):
2098 """Implements the Var syntax."""
2099 try:
2100 return self._local_scope['vars'][var_name]
2101 except KeyError:
2102 raise Exception('Var is not defined: %s' % var_name)
2103
2104 local_scope = {}
2105 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172106 'Var': _VarImpl(local_scope).Lookup,
2107 }
2108 exec contents in global_scope, local_scope
2109 return local_scope
2110
2111
2112def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082113 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412114 a set of DEPS entries that we should look up.
2115
2116 For a directory (rather than a specific filename) we fake a path to
2117 a specific filename by adding /DEPS. This is chosen as a file that
2118 will seldom or never be subject to per-file include_rules.
2119 """
[email protected]2b438d62013-11-14 17:54:142120 # We ignore deps entries on auto-generated directories.
2121 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082122
Daniel Cheng4dcdb6b2017-04-13 08:30:172123 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2124 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2125
2126 added_deps = new_deps.difference(old_deps)
2127
[email protected]2b438d62013-11-14 17:54:142128 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172129 for added_dep in added_deps:
2130 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2131 continue
2132 # Assume that a rule that ends in .h is a rule for a specific file.
2133 if added_dep.endswith('.h'):
2134 results.add(added_dep)
2135 else:
2136 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082137 return results
2138
2139
[email protected]e871964c2013-05-13 14:14:552140def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2141 """When a dependency prefixed with + is added to a DEPS file, we
2142 want to make sure that the change is reviewed by an OWNER of the
2143 target file or directory, to avoid layering violations from being
2144 introduced. This check verifies that this happens.
2145 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172146 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242147
2148 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492149 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242150 for f in input_api.AffectedFiles(include_deletes=False,
2151 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552152 filename = input_api.os_path.basename(f.LocalPath())
2153 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172154 virtual_depended_on_files.update(_CalculateAddedDeps(
2155 input_api.os_path,
2156 '\n'.join(f.OldContents()),
2157 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552158
[email protected]e871964c2013-05-13 14:14:552159 if not virtual_depended_on_files:
2160 return []
2161
2162 if input_api.is_committing:
2163 if input_api.tbr:
2164 return [output_api.PresubmitNotifyResult(
2165 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272166 if input_api.dry_run:
2167 return [output_api.PresubmitNotifyResult(
2168 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552169 if not input_api.change.issue:
2170 return [output_api.PresubmitError(
2171 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402172 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552173 output = output_api.PresubmitError
2174 else:
2175 output = output_api.PresubmitNotifyResult
2176
2177 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502178 owner_email, reviewers = (
2179 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2180 input_api,
2181 owners_db.email_regexp,
2182 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552183
2184 owner_email = owner_email or input_api.change.author_email
2185
[email protected]de4f7d22013-05-23 14:27:462186 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512187 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462188 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552189 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2190 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412191
2192 # We strip the /DEPS part that was added by
2193 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2194 # directory.
2195 def StripDeps(path):
2196 start_deps = path.rfind('/DEPS')
2197 if start_deps != -1:
2198 return path[:start_deps]
2199 else:
2200 return path
2201 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552202 for path in missing_files]
2203
2204 if unapproved_dependencies:
2205 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152206 output('You need LGTM from owners of depends-on paths in DEPS that were '
2207 'modified in this CL:\n %s' %
2208 '\n '.join(sorted(unapproved_dependencies)))]
2209 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2210 output_list.append(output(
2211 'Suggested missing target path OWNERS:\n %s' %
2212 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552213 return output_list
2214
2215 return []
2216
2217
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492218# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402219def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492220 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402221 black_list = (_EXCLUDED_PATHS +
2222 _TEST_CODE_EXCLUDED_PATHS +
2223 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042224 (r"^base[\\/]logging\.h$",
2225 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222226 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042227 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2228 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2229 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122230 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182231 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152232 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032233 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152234 r"^chrome[\\/]chrome_cleaner[\\/].*",
2235 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2236 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042237 r"^chromecast[\\/]",
2238 r"^cloud_print[\\/]",
2239 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482240 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042241 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312242 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042243 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462244 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042245 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462246 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042247 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252248 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042249 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2250 r"^courgette[\\/]courgette_tool\.cc$",
2251 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272252 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332253 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042254 r"^ipc[\\/]ipc_logging\.cc$",
2255 r"^native_client_sdk[\\/]",
2256 r"^remoting[\\/]base[\\/]logging\.h$",
2257 r"^remoting[\\/]host[\\/].*",
2258 r"^sandbox[\\/]linux[\\/].*",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332259 r"^storage[\\/]browser[\\/]fileapi[\\/]" +
2260 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042261 r"^tools[\\/]",
2262 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2263 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332264 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402265 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492266 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402267
thomasanderson625d3932017-03-29 07:16:582268 log_info = set([])
2269 printf = set([])
[email protected]85218562013-11-22 07:41:402270
2271 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582272 for _, line in f.ChangedContents():
2273 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2274 log_info.add(f.LocalPath())
2275 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2276 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372277
thomasanderson625d3932017-03-29 07:16:582278 if input_api.re.search(r"\bprintf\(", line):
2279 printf.add(f.LocalPath())
2280 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2281 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402282
2283 if log_info:
2284 return [output_api.PresubmitError(
2285 'These files spam the console log with LOG(INFO):',
2286 items=log_info)]
2287 if printf:
2288 return [output_api.PresubmitError(
2289 'These files spam the console log with printf/fprintf:',
2290 items=printf)]
2291 return []
2292
2293
[email protected]49aa76a2013-12-04 06:59:162294def _CheckForAnonymousVariables(input_api, output_api):
2295 """These types are all expected to hold locks while in scope and
2296 so should never be anonymous (which causes them to be immediately
2297 destroyed)."""
2298 they_who_must_be_named = [
2299 'base::AutoLock',
2300 'base::AutoReset',
2301 'base::AutoUnlock',
2302 'SkAutoAlphaRestore',
2303 'SkAutoBitmapShaderInstall',
2304 'SkAutoBlitterChoose',
2305 'SkAutoBounderCommit',
2306 'SkAutoCallProc',
2307 'SkAutoCanvasRestore',
2308 'SkAutoCommentBlock',
2309 'SkAutoDescriptor',
2310 'SkAutoDisableDirectionCheck',
2311 'SkAutoDisableOvalCheck',
2312 'SkAutoFree',
2313 'SkAutoGlyphCache',
2314 'SkAutoHDC',
2315 'SkAutoLockColors',
2316 'SkAutoLockPixels',
2317 'SkAutoMalloc',
2318 'SkAutoMaskFreeImage',
2319 'SkAutoMutexAcquire',
2320 'SkAutoPathBoundsUpdate',
2321 'SkAutoPDFRelease',
2322 'SkAutoRasterClipValidate',
2323 'SkAutoRef',
2324 'SkAutoTime',
2325 'SkAutoTrace',
2326 'SkAutoUnref',
2327 ]
2328 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2329 # bad: base::AutoLock(lock.get());
2330 # not bad: base::AutoLock lock(lock.get());
2331 bad_pattern = input_api.re.compile(anonymous)
2332 # good: new base::AutoLock(lock.get())
2333 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2334 errors = []
2335
2336 for f in input_api.AffectedFiles():
2337 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2338 continue
2339 for linenum, line in f.ChangedContents():
2340 if bad_pattern.search(line) and not good_pattern.search(line):
2341 errors.append('%s:%d' % (f.LocalPath(), linenum))
2342
2343 if errors:
2344 return [output_api.PresubmitError(
2345 'These lines create anonymous variables that need to be named:',
2346 items=errors)]
2347 return []
2348
2349
Peter Kasting4844e46e2018-02-23 07:27:102350def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532351 # Returns whether |template_str| is of the form <T, U...> for some types T
2352 # and U. Assumes that |template_str| is already in the form <...>.
2353 def HasMoreThanOneArg(template_str):
2354 # Level of <...> nesting.
2355 nesting = 0
2356 for c in template_str:
2357 if c == '<':
2358 nesting += 1
2359 elif c == '>':
2360 nesting -= 1
2361 elif c == ',' and nesting == 1:
2362 return True
2363 return False
2364
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492365 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102366 sources = lambda affected_file: input_api.FilterSourceFile(
2367 affected_file,
2368 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2369 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492370 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552371
2372 # Pattern to capture a single "<...>" block of template arguments. It can
2373 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2374 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2375 # latter would likely require counting that < and > match, which is not
2376 # expressible in regular languages. Should the need arise, one can introduce
2377 # limited counting (matching up to a total number of nesting depth), which
2378 # should cover all practical cases for already a low nesting limit.
2379 template_arg_pattern = (
2380 r'<[^>]*' # Opening block of <.
2381 r'>([^<]*>)?') # Closing block of >.
2382 # Prefix expressing that whatever follows is not already inside a <...>
2383 # block.
2384 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102385 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552386 not_inside_template_arg_pattern
2387 + r'\bstd::unique_ptr'
2388 + template_arg_pattern
2389 + r'\(\)')
2390
2391 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2392 template_arg_no_array_pattern = (
2393 r'<[^>]*[^]]' # Opening block of <.
2394 r'>([^(<]*[^]]>)?') # Closing block of >.
2395 # Prefix saying that what follows is the start of an expression.
2396 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2397 # Suffix saying that what follows are call parentheses with a non-empty list
2398 # of arguments.
2399 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532400 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552401 return_construct_pattern = input_api.re.compile(
2402 start_of_expr_pattern
2403 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532404 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552405 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532406 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552407 + nonempty_arg_list_pattern)
2408
Vaclav Brozek851d9602018-04-04 16:13:052409 problems_constructor = []
2410 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102411 for f in input_api.AffectedSourceFiles(sources):
2412 for line_number, line in f.ChangedContents():
2413 # Disallow:
2414 # return std::unique_ptr<T>(foo);
2415 # bar = std::unique_ptr<T>(foo);
2416 # But allow:
2417 # return std::unique_ptr<T[]>(foo);
2418 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532419 # And also allow cases when the second template argument is present. Those
2420 # cases cannot be handled by std::make_unique:
2421 # return std::unique_ptr<T, U>(foo);
2422 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052423 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532424 return_construct_result = return_construct_pattern.search(line)
2425 if return_construct_result and not HasMoreThanOneArg(
2426 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052427 problems_constructor.append(
2428 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102429 # Disallow:
2430 # std::unique_ptr<T>()
2431 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052432 problems_nullptr.append(
2433 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2434
2435 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162436 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052437 errors.append(output_api.PresubmitError(
2438 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162439 problems_nullptr))
2440 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052441 errors.append(output_api.PresubmitError(
2442 'The following files use explicit std::unique_ptr constructor.'
2443 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162444 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102445 return errors
2446
2447
[email protected]999261d2014-03-03 20:08:082448def _CheckUserActionUpdate(input_api, output_api):
2449 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522450 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082451 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522452 # If actions.xml is already included in the changelist, the PRESUBMIT
2453 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082454 return []
2455
[email protected]999261d2014-03-03 20:08:082456 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2457 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522458 current_actions = None
[email protected]999261d2014-03-03 20:08:082459 for f in input_api.AffectedFiles(file_filter=file_filter):
2460 for line_num, line in f.ChangedContents():
2461 match = input_api.re.search(action_re, line)
2462 if match:
[email protected]2f92dec2014-03-07 19:21:522463 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2464 # loaded only once.
2465 if not current_actions:
2466 with open('tools/metrics/actions/actions.xml') as actions_f:
2467 current_actions = actions_f.read()
2468 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082469 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522470 action = 'name="{0}"'.format(action_name)
2471 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082472 return [output_api.PresubmitPromptWarning(
2473 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522474 'tools/metrics/actions/actions.xml. Please run '
2475 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082476 % (f.LocalPath(), line_num, action_name))]
2477 return []
2478
2479
Daniel Cheng13ca61a882017-08-25 15:11:252480def _ImportJSONCommentEater(input_api):
2481 import sys
2482 sys.path = sys.path + [input_api.os_path.join(
2483 input_api.PresubmitLocalPath(),
2484 'tools', 'json_comment_eater')]
2485 import json_comment_eater
2486 return json_comment_eater
2487
2488
[email protected]99171a92014-06-03 08:44:472489def _GetJSONParseError(input_api, filename, eat_comments=True):
2490 try:
2491 contents = input_api.ReadFile(filename)
2492 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252493 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132494 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472495
2496 input_api.json.loads(contents)
2497 except ValueError as e:
2498 return e
2499 return None
2500
2501
2502def _GetIDLParseError(input_api, filename):
2503 try:
2504 contents = input_api.ReadFile(filename)
2505 idl_schema = input_api.os_path.join(
2506 input_api.PresubmitLocalPath(),
2507 'tools', 'json_schema_compiler', 'idl_schema.py')
2508 process = input_api.subprocess.Popen(
2509 [input_api.python_executable, idl_schema],
2510 stdin=input_api.subprocess.PIPE,
2511 stdout=input_api.subprocess.PIPE,
2512 stderr=input_api.subprocess.PIPE,
2513 universal_newlines=True)
2514 (_, error) = process.communicate(input=contents)
2515 return error or None
2516 except ValueError as e:
2517 return e
2518
2519
2520def _CheckParseErrors(input_api, output_api):
2521 """Check that IDL and JSON files do not contain syntax errors."""
2522 actions = {
2523 '.idl': _GetIDLParseError,
2524 '.json': _GetJSONParseError,
2525 }
[email protected]99171a92014-06-03 08:44:472526 # Most JSON files are preprocessed and support comments, but these do not.
2527 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042528 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472529 ]
2530 # Only run IDL checker on files in these directories.
2531 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042532 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2533 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472534 ]
2535
2536 def get_action(affected_file):
2537 filename = affected_file.LocalPath()
2538 return actions.get(input_api.os_path.splitext(filename)[1])
2539
[email protected]99171a92014-06-03 08:44:472540 def FilterFile(affected_file):
2541 action = get_action(affected_file)
2542 if not action:
2543 return False
2544 path = affected_file.LocalPath()
2545
Sean Kau46e29bc2017-08-28 16:31:162546 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472547 return False
2548
2549 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162550 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472551 return False
2552 return True
2553
2554 results = []
2555 for affected_file in input_api.AffectedFiles(
2556 file_filter=FilterFile, include_deletes=False):
2557 action = get_action(affected_file)
2558 kwargs = {}
2559 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162560 _MatchesFile(input_api, json_no_comments_patterns,
2561 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472562 kwargs['eat_comments'] = False
2563 parse_error = action(input_api,
2564 affected_file.AbsoluteLocalPath(),
2565 **kwargs)
2566 if parse_error:
2567 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2568 (affected_file.LocalPath(), parse_error)))
2569 return results
2570
2571
[email protected]760deea2013-12-10 19:33:492572def _CheckJavaStyle(input_api, output_api):
2573 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472574 import sys
[email protected]760deea2013-12-10 19:33:492575 original_sys_path = sys.path
2576 try:
2577 sys.path = sys.path + [input_api.os_path.join(
2578 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2579 import checkstyle
2580 finally:
2581 # Restore sys.path to what it was before.
2582 sys.path = original_sys_path
2583
2584 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092585 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512586 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492587
2588
Nate Fischerdfd9812e2019-07-18 22:03:002589def _CheckPythonDevilInit(input_api, output_api):
2590 """Checks to make sure devil is initialized correctly in python scripts."""
2591 script_common_initialize_pattern = input_api.re.compile(
2592 r'script_common\.InitializeEnvironment\(')
2593 devil_env_config_initialize = input_api.re.compile(
2594 r'devil_env\.config\.Initialize\(')
2595
2596 errors = []
2597
2598 sources = lambda affected_file: input_api.FilterSourceFile(
2599 affected_file,
2600 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2601 (r'^build[\\/]android[\\/]devil_chromium\.py',
2602 r'^third_party[\\/].*',)),
2603 white_list=[r'.*\.py$'])
2604
2605 for f in input_api.AffectedSourceFiles(sources):
2606 for line_num, line in f.ChangedContents():
2607 if (script_common_initialize_pattern.search(line) or
2608 devil_env_config_initialize.search(line)):
2609 errors.append("%s:%d" % (f.LocalPath(), line_num))
2610
2611 results = []
2612
2613 if errors:
2614 results.append(output_api.PresubmitError(
2615 'Devil initialization should always be done using '
2616 'devil_chromium.Initialize() in the chromium project, to use better '
2617 'defaults for dependencies (ex. up-to-date version of adb).',
2618 errors))
2619
2620 return results
2621
2622
Sean Kau46e29bc2017-08-28 16:31:162623def _MatchesFile(input_api, patterns, path):
2624 for pattern in patterns:
2625 if input_api.re.search(pattern, path):
2626 return True
2627 return False
2628
2629
Daniel Cheng7052cdf2017-11-21 19:23:292630def _GetOwnersFilesToCheckForIpcOwners(input_api):
2631 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172632
Daniel Cheng7052cdf2017-11-21 19:23:292633 Returns:
2634 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2635 contain to cover IPC-related files with noparent reviewer rules.
2636 """
2637 # Whether or not a file affects IPC is (mostly) determined by a simple list
2638 # of filename patterns.
dchenge07de812016-06-20 19:27:172639 file_patterns = [
palmerb19a0932017-01-24 04:00:312640 # Legacy IPC:
dchenge07de812016-06-20 19:27:172641 '*_messages.cc',
2642 '*_messages*.h',
2643 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312644 # Mojo IPC:
dchenge07de812016-06-20 19:27:172645 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472646 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172647 '*_struct_traits*.*',
2648 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312649 '*.typemap',
2650 # Android native IPC:
2651 '*.aidl',
2652 # Blink uses a different file naming convention:
2653 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472654 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172655 '*StructTraits*.*',
2656 '*TypeConverter*.*',
2657 ]
2658
scottmg7a6ed5ba2016-11-04 18:22:042659 # These third_party directories do not contain IPCs, but contain files
2660 # matching the above patterns, which trigger false positives.
2661 exclude_paths = [
2662 'third_party/crashpad/*',
Andres Medinae684cf42018-08-27 18:48:232663 'third_party/protobuf/benchmarks/python/*',
Daniel Chengebe635e2018-07-13 12:36:062664 'third_party/third_party/blink/renderer/platform/bindings/*',
Nico Weberee3dc9b2017-08-31 17:09:292665 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:042666 ]
2667
dchenge07de812016-06-20 19:27:172668 # Dictionary mapping an OWNERS file path to Patterns.
2669 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2670 # rules ) to a PatternEntry.
2671 # PatternEntry is a dictionary with two keys:
2672 # - 'files': the files that are matched by this pattern
2673 # - 'rules': the per-file rules needed for this pattern
2674 # For example, if we expect OWNERS file to contain rules for *.mojom and
2675 # *_struct_traits*.*, Patterns might look like this:
2676 # {
2677 # '*.mojom': {
2678 # 'files': ...,
2679 # 'rules': [
2680 # 'per-file *.mojom=set noparent',
2681 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2682 # ],
2683 # },
2684 # '*_struct_traits*.*': {
2685 # 'files': ...,
2686 # 'rules': [
2687 # 'per-file *_struct_traits*.*=set noparent',
2688 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2689 # ],
2690 # },
2691 # }
2692 to_check = {}
2693
Daniel Cheng13ca61a882017-08-25 15:11:252694 def AddPatternToCheck(input_file, pattern):
2695 owners_file = input_api.os_path.join(
2696 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2697 if owners_file not in to_check:
2698 to_check[owners_file] = {}
2699 if pattern not in to_check[owners_file]:
2700 to_check[owners_file][pattern] = {
2701 'files': [],
2702 'rules': [
2703 'per-file %s=set noparent' % pattern,
2704 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2705 ]
2706 }
Vaclav Brozekd5de76a2018-03-17 07:57:502707 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252708
dchenge07de812016-06-20 19:27:172709 # Iterate through the affected files to see what we actually need to check
2710 # for. We should only nag patch authors about per-file rules if a file in that
2711 # directory would match that pattern. If a directory only contains *.mojom
2712 # files and no *_messages*.h files, we should only nag about rules for
2713 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252714 for f in input_api.AffectedFiles(include_deletes=False):
2715 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362716 # affected files for .json, .cc, and .h files which look like they contain
2717 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162718 if (f.LocalPath().endswith('.json') and
2719 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2720 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252721 json_comment_eater = _ImportJSONCommentEater(input_api)
2722 mostly_json_lines = '\n'.join(f.NewContents())
2723 # Comments aren't allowed in strict JSON, so filter them out.
2724 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432725 try:
2726 json_content = input_api.json.loads(json_lines)
2727 except:
2728 # There's another PRESUBMIT check that already verifies that JSON files
2729 # are not invalid, so no need to emit another warning here.
2730 continue
Daniel Cheng13ca61a882017-08-25 15:11:252731 if 'interface_provider_specs' in json_content:
2732 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362733 else:
2734 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2735 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2736 if (manifest_pattern.search(f.LocalPath()) and not
2737 test_manifest_pattern.search(f.LocalPath())):
2738 # We expect all actual service manifest files to contain at least one
2739 # qualified reference to service_manager::Manifest.
2740 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2741 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172742 for pattern in file_patterns:
2743 if input_api.fnmatch.fnmatch(
2744 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042745 skip = False
2746 for exclude in exclude_paths:
2747 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2748 skip = True
2749 break
2750 if skip:
2751 continue
Daniel Cheng13ca61a882017-08-25 15:11:252752 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172753 break
2754
Daniel Cheng7052cdf2017-11-21 19:23:292755 return to_check
2756
2757
2758def _CheckIpcOwners(input_api, output_api):
2759 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2760 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2761
2762 if to_check:
2763 # If there are any OWNERS files to check, there are IPC-related changes in
2764 # this CL. Auto-CC the review list.
2765 output_api.AppendCC('[email protected]')
2766
2767 # Go through the OWNERS files to check, filtering out rules that are already
2768 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172769 for owners_file, patterns in to_check.iteritems():
2770 try:
2771 with file(owners_file) as f:
2772 lines = set(f.read().splitlines())
2773 for entry in patterns.itervalues():
2774 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2775 ]
2776 except IOError:
2777 # No OWNERS file, so all the rules are definitely missing.
2778 continue
2779
2780 # All the remaining lines weren't found in OWNERS files, so emit an error.
2781 errors = []
2782 for owners_file, patterns in to_check.iteritems():
2783 missing_lines = []
2784 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502785 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172786 missing_lines.extend(entry['rules'])
2787 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2788 if missing_lines:
2789 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:052790 'Because of the presence of files:\n%s\n\n'
2791 '%s needs the following %d lines added:\n\n%s' %
2792 ('\n'.join(files), owners_file, len(missing_lines),
2793 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:172794
2795 results = []
2796 if errors:
vabrf5ce3bf92016-07-11 14:52:412797 if input_api.is_committing:
2798 output = output_api.PresubmitError
2799 else:
2800 output = output_api.PresubmitPromptWarning
2801 results.append(output(
Daniel Cheng52111692017-06-14 08:00:592802 'Found OWNERS files that need to be updated for IPC security ' +
2803 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:172804 long_text='\n\n'.join(errors)))
2805
2806 return results
2807
2808
jbriance9e12f162016-11-25 07:57:502809def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:312810 """Checks that added or removed lines in non third party affected
2811 header files do not lead to new useless class or struct forward
2812 declaration.
jbriance9e12f162016-11-25 07:57:502813 """
2814 results = []
2815 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
2816 input_api.re.MULTILINE)
2817 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
2818 input_api.re.MULTILINE)
2819 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:312820 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:192821 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:492822 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:312823 continue
2824
jbriance9e12f162016-11-25 07:57:502825 if not f.LocalPath().endswith('.h'):
2826 continue
2827
2828 contents = input_api.ReadFile(f)
2829 fwd_decls = input_api.re.findall(class_pattern, contents)
2830 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
2831
2832 useless_fwd_decls = []
2833 for decl in fwd_decls:
2834 count = sum(1 for _ in input_api.re.finditer(
2835 r'\b%s\b' % input_api.re.escape(decl), contents))
2836 if count == 1:
2837 useless_fwd_decls.append(decl)
2838
2839 if not useless_fwd_decls:
2840 continue
2841
2842 for line in f.GenerateScmDiff().splitlines():
2843 if (line.startswith('-') and not line.startswith('--') or
2844 line.startswith('+') and not line.startswith('++')):
2845 for decl in useless_fwd_decls:
2846 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2847 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242848 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502849 (f.LocalPath(), decl)))
2850 useless_fwd_decls.remove(decl)
2851
2852 return results
2853
Jinsong Fan91ebbbd2019-04-16 14:57:172854def _CheckAndroidDebuggableBuild(input_api, output_api):
2855 """Checks that code uses BuildInfo.isDebugAndroid() instead of
2856 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
2857 this is a debuggable build of Android.
2858 """
2859 build_type_check_pattern = input_api.re.compile(
2860 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
2861
2862 errors = []
2863
2864 sources = lambda affected_file: input_api.FilterSourceFile(
2865 affected_file,
2866 black_list=(_EXCLUDED_PATHS +
2867 _TEST_CODE_EXCLUDED_PATHS +
2868 input_api.DEFAULT_BLACK_LIST +
2869 (r"^android_webview[\\/]support_library[\\/]"
2870 "boundary_interfaces[\\/]",
2871 r"^chrome[\\/]android[\\/]webapk[\\/].*",
2872 r'^third_party[\\/].*',
2873 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
2874 r"webview[\\/]chromium[\\/]License.*",)),
2875 white_list=[r'.*\.java$'])
2876
2877 for f in input_api.AffectedSourceFiles(sources):
2878 for line_num, line in f.ChangedContents():
2879 if build_type_check_pattern.search(line):
2880 errors.append("%s:%d" % (f.LocalPath(), line_num))
2881
2882 results = []
2883
2884 if errors:
2885 results.append(output_api.PresubmitPromptWarning(
2886 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
2887 ' Please use BuildInfo.isDebugAndroid() instead.',
2888 errors))
2889
2890 return results
jbriance9e12f162016-11-25 07:57:502891
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492892# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:292893def _CheckAndroidToastUsage(input_api, output_api):
2894 """Checks that code uses org.chromium.ui.widget.Toast instead of
2895 android.widget.Toast (Chromium Toast doesn't force hardware
2896 acceleration on low-end devices, saving memory).
2897 """
2898 toast_import_pattern = input_api.re.compile(
2899 r'^import android\.widget\.Toast;$')
2900
2901 errors = []
2902
2903 sources = lambda affected_file: input_api.FilterSourceFile(
2904 affected_file,
2905 black_list=(_EXCLUDED_PATHS +
2906 _TEST_CODE_EXCLUDED_PATHS +
2907 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042908 (r'^chromecast[\\/].*',
2909 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492910 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:292911
2912 for f in input_api.AffectedSourceFiles(sources):
2913 for line_num, line in f.ChangedContents():
2914 if toast_import_pattern.search(line):
2915 errors.append("%s:%d" % (f.LocalPath(), line_num))
2916
2917 results = []
2918
2919 if errors:
2920 results.append(output_api.PresubmitError(
2921 'android.widget.Toast usage is detected. Android toasts use hardware'
2922 ' acceleration, and can be\ncostly on low-end devices. Please use'
2923 ' org.chromium.ui.widget.Toast instead.\n'
2924 'Contact [email protected] if you have any questions.',
2925 errors))
2926
2927 return results
2928
2929
dgnaa68d5e2015-06-10 10:08:222930def _CheckAndroidCrLogUsage(input_api, output_api):
2931 """Checks that new logs using org.chromium.base.Log:
2932 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512933 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222934 """
pkotwicza1dd0b002016-05-16 14:41:042935
torne89540622017-03-24 19:41:302936 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042937 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302938 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:042939 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:302940 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:042941 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
2942 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:092943 # The customtabs_benchmark is a small app that does not depend on Chromium
2944 # java pieces.
Egor Paskoce145c42018-09-28 19:31:042945 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:042946 ]
2947
dgnaa68d5e2015-06-10 10:08:222948 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122949 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2950 class_in_base_pattern = input_api.re.compile(
2951 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2952 has_some_log_import_pattern = input_api.re.compile(
2953 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222954 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122955 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222956 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512957 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222958 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222959
Vincent Scheib16d7b272015-09-15 18:09:072960 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222961 'or contact [email protected] for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492962 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:042963 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122964
dgnaa68d5e2015-06-10 10:08:222965 tag_decl_errors = []
2966 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122967 tag_errors = []
dgn38736db2015-09-18 19:20:512968 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122969 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222970
2971 for f in input_api.AffectedSourceFiles(sources):
2972 file_content = input_api.ReadFile(f)
2973 has_modified_logs = False
2974
2975 # Per line checks
dgn87d9fb62015-06-12 09:15:122976 if (cr_log_import_pattern.search(file_content) or
2977 (class_in_base_pattern.search(file_content) and
2978 not has_some_log_import_pattern.search(file_content))):
2979 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222980 for line_num, line in f.ChangedContents():
2981
2982 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122983 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222984 if match:
2985 has_modified_logs = True
2986
2987 # Make sure it uses "TAG"
2988 if not match.group('tag') == 'TAG':
2989 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122990 else:
2991 # Report non cr Log function calls in changed lines
2992 for line_num, line in f.ChangedContents():
2993 if log_call_pattern.search(line):
2994 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222995
2996 # Per file checks
2997 if has_modified_logs:
2998 # Make sure the tag is using the "cr" prefix and is not too long
2999 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513000 tag_name = match.group('name') if match else None
3001 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223002 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513003 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223004 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513005 elif '.' in tag_name:
3006 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223007
3008 results = []
3009 if tag_decl_errors:
3010 results.append(output_api.PresubmitPromptWarning(
3011 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513012 '"private static final String TAG = "<package tag>".\n'
3013 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223014 tag_decl_errors))
3015
3016 if tag_length_errors:
3017 results.append(output_api.PresubmitError(
3018 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513019 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223020 tag_length_errors))
3021
3022 if tag_errors:
3023 results.append(output_api.PresubmitPromptWarning(
3024 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3025 tag_errors))
3026
dgn87d9fb62015-06-12 09:15:123027 if util_log_errors:
dgn4401aa52015-04-29 16:26:173028 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123029 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3030 util_log_errors))
3031
dgn38736db2015-09-18 19:20:513032 if tag_with_dot_errors:
3033 results.append(output_api.PresubmitPromptWarning(
3034 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3035 tag_with_dot_errors))
3036
dgn4401aa52015-04-29 16:26:173037 return results
3038
3039
Yoland Yanb92fa522017-08-28 17:37:063040def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3041 """Checks that junit.framework.* is no longer used."""
3042 deprecated_junit_framework_pattern = input_api.re.compile(
3043 r'^import junit\.framework\..*;',
3044 input_api.re.MULTILINE)
3045 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493046 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063047 errors = []
3048 for f in input_api.AffectedFiles(sources):
3049 for line_num, line in f.ChangedContents():
3050 if deprecated_junit_framework_pattern.search(line):
3051 errors.append("%s:%d" % (f.LocalPath(), line_num))
3052
3053 results = []
3054 if errors:
3055 results.append(output_api.PresubmitError(
3056 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3057 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3058 ' if you have any question.', errors))
3059 return results
3060
3061
3062def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3063 """Checks that if new Java test classes have inheritance.
3064 Either the new test class is JUnit3 test or it is a JUnit4 test class
3065 with a base class, either case is undesirable.
3066 """
3067 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3068
3069 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493070 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063071 errors = []
3072 for f in input_api.AffectedFiles(sources):
3073 if not f.OldContents():
3074 class_declaration_start_flag = False
3075 for line_num, line in f.ChangedContents():
3076 if class_declaration_pattern.search(line):
3077 class_declaration_start_flag = True
3078 if class_declaration_start_flag and ' extends ' in line:
3079 errors.append('%s:%d' % (f.LocalPath(), line_num))
3080 if '{' in line:
3081 class_declaration_start_flag = False
3082
3083 results = []
3084 if errors:
3085 results.append(output_api.PresubmitPromptWarning(
3086 'The newly created files include Test classes that inherits from base'
3087 ' class. Please do not use inheritance in JUnit4 tests or add new'
3088 ' JUnit3 tests. Contact [email protected] if you have any'
3089 ' questions.', errors))
3090 return results
3091
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203092
yolandyan45001472016-12-21 21:12:423093def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3094 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3095 deprecated_annotation_import_pattern = input_api.re.compile(
3096 r'^import android\.test\.suitebuilder\.annotation\..*;',
3097 input_api.re.MULTILINE)
3098 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493099 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423100 errors = []
3101 for f in input_api.AffectedFiles(sources):
3102 for line_num, line in f.ChangedContents():
3103 if deprecated_annotation_import_pattern.search(line):
3104 errors.append("%s:%d" % (f.LocalPath(), line_num))
3105
3106 results = []
3107 if errors:
3108 results.append(output_api.PresubmitError(
3109 'Annotations in android.test.suitebuilder.annotation have been'
3110 ' deprecated since API level 24. Please use android.support.test.filters'
3111 ' from //third_party/android_support_test_runner:runner_java instead.'
3112 ' Contact [email protected] if you have any questions.', errors))
3113 return results
3114
3115
agrieve7b6479d82015-10-07 14:24:223116def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3117 """Checks if MDPI assets are placed in a correct directory."""
3118 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3119 ('/res/drawable/' in f.LocalPath() or
3120 '/res/drawable-ldrtl/' in f.LocalPath()))
3121 errors = []
3122 for f in input_api.AffectedFiles(include_deletes=False,
3123 file_filter=file_filter):
3124 errors.append(' %s' % f.LocalPath())
3125
3126 results = []
3127 if errors:
3128 results.append(output_api.PresubmitError(
3129 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3130 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3131 '/res/drawable-ldrtl/.\n'
3132 'Contact [email protected] if you have questions.', errors))
3133 return results
3134
3135
Nate Fischer535972b2017-09-16 01:06:183136def _CheckAndroidWebkitImports(input_api, output_api):
3137 """Checks that code uses org.chromium.base.Callback instead of
3138 android.widget.ValueCallback except in the WebView glue layer.
3139 """
3140 valuecallback_import_pattern = input_api.re.compile(
3141 r'^import android\.webkit\.ValueCallback;$')
3142
3143 errors = []
3144
3145 sources = lambda affected_file: input_api.FilterSourceFile(
3146 affected_file,
3147 black_list=(_EXCLUDED_PATHS +
3148 _TEST_CODE_EXCLUDED_PATHS +
3149 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043150 (r'^android_webview[\\/]glue[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493151 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183152
3153 for f in input_api.AffectedSourceFiles(sources):
3154 for line_num, line in f.ChangedContents():
3155 if valuecallback_import_pattern.search(line):
3156 errors.append("%s:%d" % (f.LocalPath(), line_num))
3157
3158 results = []
3159
3160 if errors:
3161 results.append(output_api.PresubmitError(
3162 'android.webkit.ValueCallback usage is detected outside of the glue'
3163 ' layer. To stay compatible with the support library, android.webkit.*'
3164 ' classes should only be used inside the glue layer and'
3165 ' org.chromium.base.Callback should be used instead.',
3166 errors))
3167
3168 return results
3169
3170
Becky Zhou7c69b50992018-12-10 19:37:573171def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3172 """Checks Android XML styles """
3173 import sys
3174 original_sys_path = sys.path
3175 try:
3176 sys.path = sys.path + [input_api.os_path.join(
3177 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3178 import checkxmlstyle
3179 finally:
3180 # Restore sys.path to what it was before.
3181 sys.path = original_sys_path
3182
3183 if is_check_on_upload:
3184 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3185 else:
3186 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3187
3188
agrievef32bcc72016-04-04 14:57:403189class PydepsChecker(object):
3190 def __init__(self, input_api, pydeps_files):
3191 self._file_cache = {}
3192 self._input_api = input_api
3193 self._pydeps_files = pydeps_files
3194
3195 def _LoadFile(self, path):
3196 """Returns the list of paths within a .pydeps file relative to //."""
3197 if path not in self._file_cache:
3198 with open(path) as f:
3199 self._file_cache[path] = f.read()
3200 return self._file_cache[path]
3201
3202 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3203 """Returns an interable of paths within the .pydep, relativized to //."""
3204 os_path = self._input_api.os_path
3205 pydeps_dir = os_path.dirname(pydeps_path)
3206 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3207 if not l.startswith('*'))
3208 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3209
3210 def _CreateFilesToPydepsMap(self):
3211 """Returns a map of local_path -> list_of_pydeps."""
3212 ret = {}
3213 for pydep_local_path in self._pydeps_files:
3214 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3215 ret.setdefault(path, []).append(pydep_local_path)
3216 return ret
3217
3218 def ComputeAffectedPydeps(self):
3219 """Returns an iterable of .pydeps files that might need regenerating."""
3220 affected_pydeps = set()
3221 file_to_pydeps_map = None
3222 for f in self._input_api.AffectedFiles(include_deletes=True):
3223 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463224 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3225 # subrepositories. We can't figure out which files change, so re-check
3226 # all files.
3227 # Changes to print_python_deps.py affect all .pydeps.
3228 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403229 return self._pydeps_files
3230 elif local_path.endswith('.pydeps'):
3231 if local_path in self._pydeps_files:
3232 affected_pydeps.add(local_path)
3233 elif local_path.endswith('.py'):
3234 if file_to_pydeps_map is None:
3235 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3236 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3237 return affected_pydeps
3238
3239 def DetermineIfStale(self, pydeps_path):
3240 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413241 import difflib
John Budorick47ca3fe2018-02-10 00:53:103242 import os
3243
agrievef32bcc72016-04-04 14:57:403244 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3245 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103246 env = dict(os.environ)
3247 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403248 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103249 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413250 old_contents = old_pydeps_data[2:]
3251 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403252 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413253 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403254
3255
Tibor Goldschwendt360793f72019-06-25 18:23:493256def _ParseGclientArgs():
3257 args = {}
3258 with open('build/config/gclient_args.gni', 'r') as f:
3259 for line in f:
3260 line = line.strip()
3261 if not line or line.startswith('#'):
3262 continue
3263 attribute, value = line.split('=')
3264 args[attribute.strip()] = value.strip()
3265 return args
3266
3267
agrievef32bcc72016-04-04 14:57:403268def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3269 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403270 # This check is for Python dependency lists (.pydeps files), and involves
3271 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3272 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283273 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003274 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493275 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403276 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3277 results = []
3278 # First, check for new / deleted .pydeps.
3279 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033280 # Check whether we are running the presubmit check for a file in src.
3281 # f.LocalPath is relative to repo (src, or internal repo).
3282 # os_path.exists is relative to src repo.
3283 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3284 # to src and we can conclude that the pydeps is in src.
3285 if input_api.os_path.exists(f.LocalPath()):
3286 if f.LocalPath().endswith('.pydeps'):
3287 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3288 results.append(output_api.PresubmitError(
3289 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3290 'remove %s' % f.LocalPath()))
3291 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3292 results.append(output_api.PresubmitError(
3293 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3294 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403295
3296 if results:
3297 return results
3298
3299 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3300
3301 for pydep_path in checker.ComputeAffectedPydeps():
3302 try:
phajdan.jr0d9878552016-11-04 10:49:413303 result = checker.DetermineIfStale(pydep_path)
3304 if result:
3305 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403306 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413307 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3308 'To regenerate, run:\n\n %s' %
3309 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403310 except input_api.subprocess.CalledProcessError as error:
3311 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3312 long_text=error.output)]
3313
3314 return results
3315
3316
glidere61efad2015-02-18 17:39:433317def _CheckSingletonInHeaders(input_api, output_api):
3318 """Checks to make sure no header files have |Singleton<|."""
3319 def FileFilter(affected_file):
3320 # It's ok for base/memory/singleton.h to have |Singleton<|.
3321 black_list = (_EXCLUDED_PATHS +
3322 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043323 (r"^base[\\/]memory[\\/]singleton\.h$",
3324 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473325 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433326 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3327
sergeyu34d21222015-09-16 00:11:443328 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433329 files = []
3330 for f in input_api.AffectedSourceFiles(FileFilter):
3331 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3332 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3333 contents = input_api.ReadFile(f)
3334 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243335 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433336 pattern.search(line)):
3337 files.append(f)
3338 break
3339
3340 if files:
yolandyandaabc6d2016-04-18 18:29:393341 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443342 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433343 'Please move them to an appropriate source file so that the ' +
3344 'template gets instantiated in a single compilation unit.',
3345 files) ]
3346 return []
3347
3348
[email protected]fd20b902014-05-09 02:14:533349_DEPRECATED_CSS = [
3350 # Values
3351 ( "-webkit-box", "flex" ),
3352 ( "-webkit-inline-box", "inline-flex" ),
3353 ( "-webkit-flex", "flex" ),
3354 ( "-webkit-inline-flex", "inline-flex" ),
3355 ( "-webkit-min-content", "min-content" ),
3356 ( "-webkit-max-content", "max-content" ),
3357
3358 # Properties
3359 ( "-webkit-background-clip", "background-clip" ),
3360 ( "-webkit-background-origin", "background-origin" ),
3361 ( "-webkit-background-size", "background-size" ),
3362 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443363 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533364
3365 # Functions
3366 ( "-webkit-gradient", "gradient" ),
3367 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3368 ( "-webkit-linear-gradient", "linear-gradient" ),
3369 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3370 ( "-webkit-radial-gradient", "radial-gradient" ),
3371 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3372]
3373
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203374
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493375# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243376def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533377 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253378 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343379 documentation and iOS CSS for dom distiller
3380 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253381 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533382 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493383 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253384 black_list = (_EXCLUDED_PATHS +
3385 _TEST_CODE_EXCLUDED_PATHS +
3386 input_api.DEFAULT_BLACK_LIST +
3387 (r"^chrome/common/extensions/docs",
3388 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343389 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443390 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253391 r"^native_client_sdk"))
3392 file_filter = lambda f: input_api.FilterSourceFile(
3393 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533394 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3395 for line_num, line in fpath.ChangedContents():
3396 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023397 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533398 results.append(output_api.PresubmitError(
3399 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3400 (fpath.LocalPath(), line_num, deprecated_value, value)))
3401 return results
3402
mohan.reddyf21db962014-10-16 12:26:473403
rlanday6802cf632017-05-30 17:48:363404def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363405 bad_files = {}
3406 for f in input_api.AffectedFiles(include_deletes=False):
3407 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493408 not f.LocalPath().startswith('third_party/blink') and
3409 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363410 continue
3411
Daniel Bratell65b033262019-04-23 08:17:063412 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363413 continue
3414
Vaclav Brozekd5de76a2018-03-17 07:57:503415 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363416 if "#include" in line and "../" in line]
3417 if not relative_includes:
3418 continue
3419 bad_files[f.LocalPath()] = relative_includes
3420
3421 if not bad_files:
3422 return []
3423
3424 error_descriptions = []
3425 for file_path, bad_lines in bad_files.iteritems():
3426 error_description = file_path
3427 for line in bad_lines:
3428 error_description += '\n ' + line
3429 error_descriptions.append(error_description)
3430
3431 results = []
3432 results.append(output_api.PresubmitError(
3433 'You added one or more relative #include paths (including "../").\n'
3434 'These shouldn\'t be used because they can be used to include headers\n'
3435 'from code that\'s not correctly specified as a dependency in the\n'
3436 'relevant BUILD.gn file(s).',
3437 error_descriptions))
3438
3439 return results
3440
Takeshi Yoshinoe387aa32017-08-02 13:16:133441
Daniel Bratell65b033262019-04-23 08:17:063442def _CheckForCcIncludes(input_api, output_api):
3443 """Check that nobody tries to include a cc file. It's a relatively
3444 common error which results in duplicate symbols in object
3445 files. This may not always break the build until someone later gets
3446 very confusing linking errors."""
3447 results = []
3448 for f in input_api.AffectedFiles(include_deletes=False):
3449 # We let third_party code do whatever it wants
3450 if (f.LocalPath().startswith('third_party') and
3451 not f.LocalPath().startswith('third_party/blink') and
3452 not f.LocalPath().startswith('third_party\\blink')):
3453 continue
3454
3455 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3456 continue
3457
3458 for _, line in f.ChangedContents():
3459 if line.startswith('#include "'):
3460 included_file = line.split('"')[1]
3461 if _IsCPlusPlusFile(input_api, included_file):
3462 # The most common naming for external files with C++ code,
3463 # apart from standard headers, is to call them foo.inc, but
3464 # Chromium sometimes uses foo-inc.cc so allow that as well.
3465 if not included_file.endswith(('.h', '-inc.cc')):
3466 results.append(output_api.PresubmitError(
3467 'Only header files or .inc files should be included in other\n'
3468 'C++ files. Compiling the contents of a cc file more than once\n'
3469 'will cause duplicate information in the build which may later\n'
3470 'result in strange link_errors.\n' +
3471 f.LocalPath() + ':\n ' +
3472 line))
3473
3474 return results
3475
3476
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203477def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3478 if not isinstance(key, ast.Str):
3479 return 'Key at line %d must be a string literal' % key.lineno
3480 if not isinstance(value, ast.Dict):
3481 return 'Value at line %d must be a dict' % value.lineno
3482 if len(value.keys) != 1:
3483 return 'Dict at line %d must have single entry' % value.lineno
3484 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3485 return (
3486 'Entry at line %d must have a string literal \'filepath\' as key' %
3487 value.lineno)
3488 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133489
Takeshi Yoshinoe387aa32017-08-02 13:16:133490
Sergey Ulanov4af16052018-11-08 02:41:463491def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203492 if not isinstance(key, ast.Str):
3493 return 'Key at line %d must be a string literal' % key.lineno
3494 if not isinstance(value, ast.List):
3495 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463496 for element in value.elts:
3497 if not isinstance(element, ast.Str):
3498 return 'Watchlist elements on line %d is not a string' % key.lineno
3499 if not email_regex.match(element.s):
3500 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3501 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203502 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133503
Takeshi Yoshinoe387aa32017-08-02 13:16:133504
Sergey Ulanov4af16052018-11-08 02:41:463505def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203506 mismatch_template = (
3507 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3508 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133509
Sergey Ulanov4af16052018-11-08 02:41:463510 email_regex = input_api.re.compile(
3511 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3512
3513 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203514 i = 0
3515 last_key = ''
3516 while True:
3517 if i >= len(wd_dict.keys):
3518 if i >= len(w_dict.keys):
3519 return None
3520 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3521 elif i >= len(w_dict.keys):
3522 return (
3523 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133524
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203525 wd_key = wd_dict.keys[i]
3526 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133527
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203528 result = _CheckWatchlistDefinitionsEntrySyntax(
3529 wd_key, wd_dict.values[i], ast)
3530 if result is not None:
3531 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133532
Sergey Ulanov4af16052018-11-08 02:41:463533 result = _CheckWatchlistsEntrySyntax(
3534 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203535 if result is not None:
3536 return 'Bad entry in WATCHLISTS dict: %s' % result
3537
3538 if wd_key.s != w_key.s:
3539 return mismatch_template % (
3540 '%s at line %d' % (wd_key.s, wd_key.lineno),
3541 '%s at line %d' % (w_key.s, w_key.lineno))
3542
3543 if wd_key.s < last_key:
3544 return (
3545 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3546 (wd_key.lineno, w_key.lineno))
3547 last_key = wd_key.s
3548
3549 i = i + 1
3550
3551
Sergey Ulanov4af16052018-11-08 02:41:463552def _CheckWATCHLISTSSyntax(expression, input_api):
3553 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203554 if not isinstance(expression, ast.Expression):
3555 return 'WATCHLISTS file must contain a valid expression'
3556 dictionary = expression.body
3557 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3558 return 'WATCHLISTS file must have single dict with exactly two entries'
3559
3560 first_key = dictionary.keys[0]
3561 first_value = dictionary.values[0]
3562 second_key = dictionary.keys[1]
3563 second_value = dictionary.values[1]
3564
3565 if (not isinstance(first_key, ast.Str) or
3566 first_key.s != 'WATCHLIST_DEFINITIONS' or
3567 not isinstance(first_value, ast.Dict)):
3568 return (
3569 'The first entry of the dict in WATCHLISTS file must be '
3570 'WATCHLIST_DEFINITIONS dict')
3571
3572 if (not isinstance(second_key, ast.Str) or
3573 second_key.s != 'WATCHLISTS' or
3574 not isinstance(second_value, ast.Dict)):
3575 return (
3576 'The second entry of the dict in WATCHLISTS file must be '
3577 'WATCHLISTS dict')
3578
Sergey Ulanov4af16052018-11-08 02:41:463579 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133580
3581
3582def _CheckWATCHLISTS(input_api, output_api):
3583 for f in input_api.AffectedFiles(include_deletes=False):
3584 if f.LocalPath() == 'WATCHLISTS':
3585 contents = input_api.ReadFile(f, 'r')
3586
3587 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203588 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133589 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203590 # Get an AST tree for it and scan the tree for detailed style checking.
3591 expression = input_api.ast.parse(
3592 contents, filename='WATCHLISTS', mode='eval')
3593 except ValueError as e:
3594 return [output_api.PresubmitError(
3595 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3596 except SyntaxError as e:
3597 return [output_api.PresubmitError(
3598 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3599 except TypeError as e:
3600 return [output_api.PresubmitError(
3601 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133602
Sergey Ulanov4af16052018-11-08 02:41:463603 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203604 if result is not None:
3605 return [output_api.PresubmitError(result)]
3606 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133607
3608 return []
3609
3610
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193611def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3612 """Checks that newly added header files have corresponding GN changes.
3613 Note that this is only a heuristic. To be precise, run script:
3614 build/check_gn_headers.py.
3615 """
3616
3617 def headers(f):
3618 return input_api.FilterSourceFile(
3619 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3620
3621 new_headers = []
3622 for f in input_api.AffectedSourceFiles(headers):
3623 if f.Action() != 'A':
3624 continue
3625 new_headers.append(f.LocalPath())
3626
3627 def gn_files(f):
3628 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3629
3630 all_gn_changed_contents = ''
3631 for f in input_api.AffectedSourceFiles(gn_files):
3632 for _, line in f.ChangedContents():
3633 all_gn_changed_contents += line
3634
3635 problems = []
3636 for header in new_headers:
3637 basename = input_api.os_path.basename(header)
3638 if basename not in all_gn_changed_contents:
3639 problems.append(header)
3640
3641 if problems:
3642 return [output_api.PresubmitPromptWarning(
3643 'Missing GN changes for new header files', items=sorted(problems),
3644 long_text='Please double check whether newly added header files need '
3645 'corresponding changes in gn or gni files.\nThis checking is only a '
3646 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3647 'Read https://crbug.com/661774 for more info.')]
3648 return []
3649
3650
Michael Giuffridad3bc8672018-10-25 22:48:023651def _CheckCorrectProductNameInMessages(input_api, output_api):
3652 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3653
3654 This assumes we won't intentionally reference one product from the other
3655 product.
3656 """
3657 all_problems = []
3658 test_cases = [{
3659 "filename_postfix": "google_chrome_strings.grd",
3660 "correct_name": "Chrome",
3661 "incorrect_name": "Chromium",
3662 }, {
3663 "filename_postfix": "chromium_strings.grd",
3664 "correct_name": "Chromium",
3665 "incorrect_name": "Chrome",
3666 }]
3667
3668 for test_case in test_cases:
3669 problems = []
3670 filename_filter = lambda x: x.LocalPath().endswith(
3671 test_case["filename_postfix"])
3672
3673 # Check each new line. Can yield false positives in multiline comments, but
3674 # easier than trying to parse the XML because messages can have nested
3675 # children, and associating message elements with affected lines is hard.
3676 for f in input_api.AffectedSourceFiles(filename_filter):
3677 for line_num, line in f.ChangedContents():
3678 if "<message" in line or "<!--" in line or "-->" in line:
3679 continue
3680 if test_case["incorrect_name"] in line:
3681 problems.append(
3682 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3683
3684 if problems:
3685 message = (
3686 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3687 % (test_case["correct_name"], test_case["correct_name"],
3688 test_case["incorrect_name"]))
3689 all_problems.append(
3690 output_api.PresubmitPromptWarning(message, items=problems))
3691
3692 return all_problems
3693
3694
Dirk Pranke3c18a382019-03-15 01:07:513695def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3696 # TODO(crbug.com/941824): We need to make sure the entries in
3697 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3698 # so that users of //buildtools in other projects get the same tooling
3699 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3700 # support to gclient, we can eliminate the duplication and delete
3701 # this presubmit check.
3702
3703 # Update this regexp if new revisions are added to the files.
3704 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013705 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513706
3707 # If a user is changing one revision, they need to change the same
3708 # line in both files. This means that any given change should contain
3709 # exactly the same list of changed lines that match the regexps. The
3710 # replace(' ', '') call allows us to ignore whitespace changes to the
3711 # lines. The 'long_text' parameter to the error will contain the
3712 # list of changed lines in both files, which should make it easy enough
3713 # to spot the error without going overboard in this implementation.
3714 revs_changes = {
3715 'DEPS': {},
3716 'buildtools/DEPS': {},
3717 }
3718 long_text = ''
3719
3720 for f in input_api.AffectedFiles(
3721 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3722 for line_num, line in f.ChangedContents():
3723 if rev_regexp.search(line):
3724 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3725 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3726
3727 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3728 return [output_api.PresubmitError(
3729 'Change buildtools revisions in sync in both //DEPS and '
3730 '//buildtools/DEPS.', long_text=long_text + '\n')]
3731 else:
3732 return []
3733
3734
Daniel Bratell93eb6c62019-04-29 20:13:363735def _CheckForTooLargeFiles(input_api, output_api):
3736 """Avoid large files, especially binary files, in the repository since
3737 git doesn't scale well for those. They will be in everyone's repo
3738 clones forever, forever making Chromium slower to clone and work
3739 with."""
3740
3741 # Uploading files to cloud storage is not trivial so we don't want
3742 # to set the limit too low, but the upper limit for "normal" large
3743 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
3744 # anything over 20 MB is exceptional.
3745 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
3746
3747 too_large_files = []
3748 for f in input_api.AffectedFiles():
3749 # Check both added and modified files (but not deleted files).
3750 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:383751 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:363752 if size > TOO_LARGE_FILE_SIZE_LIMIT:
3753 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
3754
3755 if too_large_files:
3756 message = (
3757 'Do not commit large files to git since git scales badly for those.\n' +
3758 'Instead put the large files in cloud storage and use DEPS to\n' +
3759 'fetch them.\n' + '\n'.join(too_large_files)
3760 )
3761 return [output_api.PresubmitError(
3762 'Too large files found in commit', long_text=message + '\n')]
3763 else:
3764 return []
3765
dgnaa68d5e2015-06-10 10:08:223766def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:573767 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:223768 results = []
dgnaa68d5e2015-06-10 10:08:223769 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:173770 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:223771 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:293772 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:063773 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
3774 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:423775 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:183776 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:573777 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
3778 return results
3779
3780def _AndroidSpecificOnCommitChecks(input_api, output_api):
3781 """Groups commit checks that target android code."""
3782 results = []
3783 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:223784 return results
3785
3786
[email protected]22c9bd72011-03-27 16:47:393787def _CommonChecks(input_api, output_api):
3788 """Checks common to both upload and commit."""
3789 results = []
3790 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:383791 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:543792 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:083793
3794 author = input_api.change.author_email
3795 if author and author not in _KNOWN_ROBOTS:
3796 results.extend(
3797 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
3798
[email protected]55459852011-08-10 15:17:193799 results.extend(
[email protected]760deea2013-12-10 19:33:493800 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:233801 results.extend(
3802 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:543803 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:183804 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:343805 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:523806 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:223807 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:443808 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:593809 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:063810 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:123811 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:183812 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:223813 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:303814 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:493815 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:033816 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:493817 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:443818 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:273819 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:073820 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:543821 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:443822 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:393823 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:553824 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:043825 results.extend(
3826 input_api.canned_checks.CheckChangeHasNoTabs(
3827 input_api,
3828 output_api,
3829 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:403830 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:163831 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:083832 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:243833 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:473834 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:043835 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:053836 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:143837 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:233838 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:433839 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:403840 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:153841 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:173842 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:503843 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:363844 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:063845 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:133846 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:433847 results.extend(input_api.RunTests(
3848 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143849 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:023850 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:513851 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:363852 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:003853 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:243854
Vaclav Brozekcdc7defb2018-03-20 09:54:353855 for f in input_api.AffectedFiles():
3856 path, name = input_api.os_path.split(f.LocalPath())
3857 if name == 'PRESUBMIT.py':
3858 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:003859 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
3860 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:073861 # The PRESUBMIT.py file (and the directory containing it) might
3862 # have been affected by being moved or removed, so only try to
3863 # run the tests if they still exist.
3864 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
3865 input_api, output_api, full_path,
3866 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:393867 return results
[email protected]1f7b4172010-01-28 01:17:343868
[email protected]b337cb5b2011-01-23 21:24:053869
[email protected]b8079ae4a2012-12-05 19:56:493870def _CheckPatchFiles(input_api, output_api):
3871 problems = [f.LocalPath() for f in input_api.AffectedFiles()
3872 if f.LocalPath().endswith(('.orig', '.rej'))]
3873 if problems:
3874 return [output_api.PresubmitError(
3875 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:033876 else:
3877 return []
[email protected]b8079ae4a2012-12-05 19:56:493878
3879
Kent Tamura5a8755d2017-06-29 23:37:073880def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:213881 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
3882 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
3883 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:073884 include_re = input_api.re.compile(
3885 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
3886 extension_re = input_api.re.compile(r'\.[a-z]+$')
3887 errors = []
3888 for f in input_api.AffectedFiles():
3889 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
3890 continue
3891 found_line_number = None
3892 found_macro = None
3893 for line_num, line in f.ChangedContents():
3894 match = macro_re.search(line)
3895 if match:
3896 found_line_number = line_num
3897 found_macro = match.group(2)
3898 break
3899 if not found_line_number:
3900 continue
3901
3902 found_include = False
3903 for line in f.NewContents():
3904 if include_re.search(line):
3905 found_include = True
3906 break
3907 if found_include:
3908 continue
3909
3910 if not f.LocalPath().endswith('.h'):
3911 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
3912 try:
3913 content = input_api.ReadFile(primary_header_path, 'r')
3914 if include_re.search(content):
3915 continue
3916 except IOError:
3917 pass
3918 errors.append('%s:%d %s macro is used without including build/'
3919 'build_config.h.'
3920 % (f.LocalPath(), found_line_number, found_macro))
3921 if errors:
3922 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
3923 return []
3924
3925
[email protected]b00342e7f2013-03-26 16:21:543926def _DidYouMeanOSMacro(bad_macro):
3927 try:
3928 return {'A': 'OS_ANDROID',
3929 'B': 'OS_BSD',
3930 'C': 'OS_CHROMEOS',
3931 'F': 'OS_FREEBSD',
3932 'L': 'OS_LINUX',
3933 'M': 'OS_MACOSX',
3934 'N': 'OS_NACL',
3935 'O': 'OS_OPENBSD',
3936 'P': 'OS_POSIX',
3937 'S': 'OS_SOLARIS',
3938 'W': 'OS_WIN'}[bad_macro[3].upper()]
3939 except KeyError:
3940 return ''
3941
3942
3943def _CheckForInvalidOSMacrosInFile(input_api, f):
3944 """Check for sensible looking, totally invalid OS macros."""
3945 preprocessor_statement = input_api.re.compile(r'^\s*#')
3946 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
3947 results = []
3948 for lnum, line in f.ChangedContents():
3949 if preprocessor_statement.search(line):
3950 for match in os_macro.finditer(line):
3951 if not match.group(1) in _VALID_OS_MACROS:
3952 good = _DidYouMeanOSMacro(match.group(1))
3953 did_you_mean = ' (did you mean %s?)' % good if good else ''
3954 results.append(' %s:%d %s%s' % (f.LocalPath(),
3955 lnum,
3956 match.group(1),
3957 did_you_mean))
3958 return results
3959
3960
3961def _CheckForInvalidOSMacros(input_api, output_api):
3962 """Check all affected files for invalid OS macros."""
3963 bad_macros = []
tzik3f295992018-12-04 20:32:233964 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:473965 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:543966 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
3967
3968 if not bad_macros:
3969 return []
3970
3971 return [output_api.PresubmitError(
3972 'Possibly invalid OS macro[s] found. Please fix your code\n'
3973 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
3974
lliabraa35bab3932014-10-01 12:16:443975
3976def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
3977 """Check all affected files for invalid "if defined" macros."""
3978 ALWAYS_DEFINED_MACROS = (
3979 "TARGET_CPU_PPC",
3980 "TARGET_CPU_PPC64",
3981 "TARGET_CPU_68K",
3982 "TARGET_CPU_X86",
3983 "TARGET_CPU_ARM",
3984 "TARGET_CPU_MIPS",
3985 "TARGET_CPU_SPARC",
3986 "TARGET_CPU_ALPHA",
3987 "TARGET_IPHONE_SIMULATOR",
3988 "TARGET_OS_EMBEDDED",
3989 "TARGET_OS_IPHONE",
3990 "TARGET_OS_MAC",
3991 "TARGET_OS_UNIX",
3992 "TARGET_OS_WIN32",
3993 )
3994 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
3995 results = []
3996 for lnum, line in f.ChangedContents():
3997 for match in ifdef_macro.finditer(line):
3998 if match.group(1) in ALWAYS_DEFINED_MACROS:
3999 always_defined = ' %s is always defined. ' % match.group(1)
4000 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4001 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4002 lnum,
4003 always_defined,
4004 did_you_mean))
4005 return results
4006
4007
4008def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4009 """Check all affected files for invalid "if defined" macros."""
4010 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054011 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444012 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054013 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214014 continue
lliabraa35bab3932014-10-01 12:16:444015 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4016 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4017
4018 if not bad_macros:
4019 return []
4020
4021 return [output_api.PresubmitError(
4022 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4023 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4024 bad_macros)]
4025
4026
mlamouria82272622014-09-16 18:45:044027def _CheckForIPCRules(input_api, output_api):
4028 """Check for same IPC rules described in
4029 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4030 """
4031 base_pattern = r'IPC_ENUM_TRAITS\('
4032 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4033 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4034
4035 problems = []
4036 for f in input_api.AffectedSourceFiles(None):
4037 local_path = f.LocalPath()
4038 if not local_path.endswith('.h'):
4039 continue
4040 for line_number, line in f.ChangedContents():
4041 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4042 problems.append(
4043 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4044
4045 if problems:
4046 return [output_api.PresubmitPromptWarning(
4047 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4048 else:
4049 return []
4050
[email protected]b00342e7f2013-03-26 16:21:544051
Stephen Martinis97a394142018-06-07 23:06:054052def _CheckForLongPathnames(input_api, output_api):
4053 """Check to make sure no files being submitted have long paths.
4054 This causes issues on Windows.
4055 """
4056 problems = []
4057 for f in input_api.AffectedSourceFiles(None):
4058 local_path = f.LocalPath()
4059 # Windows has a path limit of 260 characters. Limit path length to 200 so
4060 # that we have some extra for the prefix on dev machines and the bots.
4061 if len(local_path) > 200:
4062 problems.append(local_path)
4063
4064 if problems:
4065 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4066 else:
4067 return []
4068
4069
Daniel Bratell8ba52722018-03-02 16:06:144070def _CheckForIncludeGuards(input_api, output_api):
4071 """Check that header files have proper guards against multiple inclusion.
4072 If a file should not have such guards (and it probably should) then it
4073 should include the string "no-include-guard-because-multiply-included".
4074 """
Daniel Bratell6a75baef62018-06-04 10:04:454075 def is_chromium_header_file(f):
4076 # We only check header files under the control of the Chromium
4077 # project. That is, those outside third_party apart from
4078 # third_party/blink.
4079 file_with_path = input_api.os_path.normpath(f.LocalPath())
4080 return (file_with_path.endswith('.h') and
4081 (not file_with_path.startswith('third_party') or
4082 file_with_path.startswith(
4083 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144084
4085 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344086 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144087
4088 errors = []
4089
Daniel Bratell6a75baef62018-06-04 10:04:454090 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144091 guard_name = None
4092 guard_line_number = None
4093 seen_guard_end = False
4094
4095 file_with_path = input_api.os_path.normpath(f.LocalPath())
4096 base_file_name = input_api.os_path.splitext(
4097 input_api.os_path.basename(file_with_path))[0]
4098 upper_base_file_name = base_file_name.upper()
4099
4100 expected_guard = replace_special_with_underscore(
4101 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144102
4103 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574104 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4105 # are too many (1000+) files with slight deviations from the
4106 # coding style. The most important part is that the include guard
4107 # is there, and that it's unique, not the name so this check is
4108 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144109 #
4110 # As code becomes more uniform, this could be made stricter.
4111
4112 guard_name_pattern_list = [
4113 # Anything with the right suffix (maybe with an extra _).
4114 r'\w+_H__?',
4115
Daniel Bratell39b5b062018-05-16 18:09:574116 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144117 r'\w+_h',
4118
4119 # Anything including the uppercase name of the file.
4120 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4121 upper_base_file_name)) + r'\w*',
4122 ]
4123 guard_name_pattern = '|'.join(guard_name_pattern_list)
4124 guard_pattern = input_api.re.compile(
4125 r'#ifndef\s+(' + guard_name_pattern + ')')
4126
4127 for line_number, line in enumerate(f.NewContents()):
4128 if 'no-include-guard-because-multiply-included' in line:
4129 guard_name = 'DUMMY' # To not trigger check outside the loop.
4130 break
4131
4132 if guard_name is None:
4133 match = guard_pattern.match(line)
4134 if match:
4135 guard_name = match.group(1)
4136 guard_line_number = line_number
4137
Daniel Bratell39b5b062018-05-16 18:09:574138 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454139 # don't match the chromium style guide, but new files should
4140 # get it right.
4141 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574142 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144143 errors.append(output_api.PresubmitPromptWarning(
4144 'Header using the wrong include guard name %s' % guard_name,
4145 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell39b5b062018-05-16 18:09:574146 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144147 else:
4148 # The line after #ifndef should have a #define of the same name.
4149 if line_number == guard_line_number + 1:
4150 expected_line = '#define %s' % guard_name
4151 if line != expected_line:
4152 errors.append(output_api.PresubmitPromptWarning(
4153 'Missing "%s" for include guard' % expected_line,
4154 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4155 'Expected: %r\nGot: %r' % (expected_line, line)))
4156
4157 if not seen_guard_end and line == '#endif // %s' % guard_name:
4158 seen_guard_end = True
4159 elif seen_guard_end:
4160 if line.strip() != '':
4161 errors.append(output_api.PresubmitPromptWarning(
4162 'Include guard %s not covering the whole file' % (
4163 guard_name), [f.LocalPath()]))
4164 break # Nothing else to check and enough to warn once.
4165
4166 if guard_name is None:
4167 errors.append(output_api.PresubmitPromptWarning(
4168 'Missing include guard %s' % expected_guard,
4169 [f.LocalPath()],
4170 'Missing include guard in %s\n'
4171 'Recommended name: %s\n'
4172 'This check can be disabled by having the string\n'
4173 'no-include-guard-because-multiply-included in the header.' %
4174 (f.LocalPath(), expected_guard)))
4175
4176 return errors
4177
4178
mostynbb639aca52015-01-07 20:31:234179def _CheckForWindowsLineEndings(input_api, output_api):
4180 """Check source code and known ascii text files for Windows style line
4181 endings.
4182 """
earthdok1b5e0ee2015-03-10 15:19:104183 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234184
4185 file_inclusion_pattern = (
4186 known_text_files,
4187 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4188 )
4189
mostynbb639aca52015-01-07 20:31:234190 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534191 source_file_filter = lambda f: input_api.FilterSourceFile(
4192 f, white_list=file_inclusion_pattern, black_list=None)
4193 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504194 include_file = False
4195 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234196 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504197 include_file = True
4198 if include_file:
4199 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234200
4201 if problems:
4202 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4203 'these files to contain Windows style line endings?\n' +
4204 '\n'.join(problems))]
4205
4206 return []
4207
4208
Vaclav Brozekd5de76a2018-03-17 07:57:504209def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134210 """Checks that all source files use SYSLOG properly."""
4211 syslog_files = []
4212 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564213 for line_number, line in f.ChangedContents():
4214 if 'SYSLOG' in line:
4215 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4216
pastarmovj89f7ee12016-09-20 14:58:134217 if syslog_files:
4218 return [output_api.PresubmitPromptWarning(
4219 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4220 ' calls.\nFiles to check:\n', items=syslog_files)]
4221 return []
4222
4223
[email protected]1f7b4172010-01-28 01:17:344224def CheckChangeOnUpload(input_api, output_api):
4225 results = []
4226 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474227 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284228 results.extend(
jam93a6ee792017-02-08 23:59:224229 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194230 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224231 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134232 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164233 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534234 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194235 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544236 return results
[email protected]ca8d1982009-02-19 16:33:124237
4238
[email protected]1bfb8322014-04-23 01:02:414239def GetTryServerMasterForBot(bot):
4240 """Returns the Try Server master for the given bot.
4241
[email protected]0bb112362014-07-26 04:38:324242 It tries to guess the master from the bot name, but may still fail
4243 and return None. There is no longer a default master.
4244 """
4245 # Potentially ambiguous bot names are listed explicitly.
4246 master_map = {
tandriie5587792016-07-14 00:34:504247 'chromium_presubmit': 'master.tryserver.chromium.linux',
4248 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414249 }
[email protected]0bb112362014-07-26 04:38:324250 master = master_map.get(bot)
4251 if not master:
wnwen4fbaab82016-05-25 12:54:364252 if 'android' in bot:
tandriie5587792016-07-14 00:34:504253 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364254 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504255 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324256 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504257 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324258 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504259 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324260 return master
[email protected]1bfb8322014-04-23 01:02:414261
4262
[email protected]ca8d1982009-02-19 16:33:124263def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544264 results = []
[email protected]1f7b4172010-01-28 01:17:344265 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574266 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544267 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274268 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344269 input_api,
4270 output_api,
[email protected]2fdd1f362013-01-16 03:56:034271 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274272
jam93a6ee792017-02-08 23:59:224273 results.extend(
4274 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544275 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4276 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414277 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4278 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544279 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144280
4281
4282def _CheckTranslationScreenshots(input_api, output_api):
4283 PART_FILE_TAG = "part"
4284 import os
4285 import sys
4286 from io import StringIO
4287
4288 try:
4289 old_sys_path = sys.path
4290 sys.path = sys.path + [input_api.os_path.join(
4291 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4292 import grit.grd_reader
4293 import grit.node.message
4294 import grit.util
4295 finally:
4296 sys.path = old_sys_path
4297
4298 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4299 """Load the grd file and return a dict of message ids to messages.
4300
4301 Ignores any nested grdp files pointed by <part> tag.
4302 """
4303 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4304 stop_after=None, first_ids_file=None,
Julian Pastarmov4f7af532019-07-17 19:25:374305 debug=False, defines={'_chromium': 1},
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144306 tags_to_ignore=set([PART_FILE_TAG]))
4307 return {
4308 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4309 grit.node.message.MessageNode)
4310 }
4311
4312 def _GetGrdpMessagesFromString(grdp_string):
4313 """Parses the contents of a grdp file given in grdp_string.
4314
4315 grd_reader can't parse grdp files directly. Instead, this creates a
4316 temporary directory with a grd file pointing to the grdp file, and loads the
4317 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4318 """
4319 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4320 <grit latest_public_release="1" current_release="1">
4321 <release seq="1">
4322 <messages>
4323 <part file="sub.grdp" />
4324 </messages>
4325 </release>
4326 </grit>
4327 """
4328 with grit.util.TempDir({'main.grd': WRAPPER,
4329 'sub.grdp': grdp_string}) as temp_dir:
4330 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4331
4332 new_or_added_paths = set(f.LocalPath()
4333 for f in input_api.AffectedFiles()
4334 if (f.Action() == 'A' or f.Action() == 'M'))
4335 removed_paths = set(f.LocalPath()
4336 for f in input_api.AffectedFiles(include_deletes=True)
4337 if f.Action() == 'D')
4338
4339 affected_grds = [f for f in input_api.AffectedFiles()
4340 if (f.LocalPath().endswith('.grd') or
4341 f.LocalPath().endswith('.grdp'))]
4342 affected_png_paths = [f.AbsoluteLocalPath()
4343 for f in input_api.AffectedFiles()
4344 if (f.LocalPath().endswith('.png'))]
4345
4346 # Check for screenshots. Developers can upload screenshots using
4347 # tools/translation/upload_screenshots.py which finds and uploads
4348 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4349 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4350 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4351 #
4352 # The logic here is as follows:
4353 #
4354 # - If the CL has a .png file under the screenshots directory for a grd
4355 # file, warn the developer. Actual images should never be checked into the
4356 # Chrome repo.
4357 #
4358 # - If the CL contains modified or new messages in grd files and doesn't
4359 # contain the corresponding .sha1 files, warn the developer to add images
4360 # and upload them via tools/translation/upload_screenshots.py.
4361 #
4362 # - If the CL contains modified or new messages in grd files and the
4363 # corresponding .sha1 files, everything looks good.
4364 #
4365 # - If the CL contains removed messages in grd files but the corresponding
4366 # .sha1 files aren't removed, warn the developer to remove them.
4367 unnecessary_screenshots = []
4368 missing_sha1 = []
4369 unnecessary_sha1_files = []
4370
4371
4372 def _CheckScreenshotAdded(screenshots_dir, message_id):
4373 sha1_path = input_api.os_path.join(
4374 screenshots_dir, message_id + '.png.sha1')
4375 if sha1_path not in new_or_added_paths:
4376 missing_sha1.append(sha1_path)
4377
4378
4379 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4380 sha1_path = input_api.os_path.join(
4381 screenshots_dir, message_id + '.png.sha1')
4382 if sha1_path not in removed_paths:
4383 unnecessary_sha1_files.append(sha1_path)
4384
4385
4386 for f in affected_grds:
4387 file_path = f.LocalPath()
4388 old_id_to_msg_map = {}
4389 new_id_to_msg_map = {}
4390 if file_path.endswith('.grdp'):
4391 if f.OldContents():
4392 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394393 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144394 if f.NewContents():
4395 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394396 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144397 else:
4398 if f.OldContents():
4399 old_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394400 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144401 if f.NewContents():
4402 new_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394403 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144404
4405 # Compute added, removed and modified message IDs.
4406 old_ids = set(old_id_to_msg_map)
4407 new_ids = set(new_id_to_msg_map)
4408 added_ids = new_ids - old_ids
4409 removed_ids = old_ids - new_ids
4410 modified_ids = set([])
4411 for key in old_ids.intersection(new_ids):
4412 if (old_id_to_msg_map[key].FormatXml()
4413 != new_id_to_msg_map[key].FormatXml()):
4414 modified_ids.add(key)
4415
4416 grd_name, ext = input_api.os_path.splitext(
4417 input_api.os_path.basename(file_path))
4418 screenshots_dir = input_api.os_path.join(
4419 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4420
4421 # Check the screenshot directory for .png files. Warn if there is any.
4422 for png_path in affected_png_paths:
4423 if png_path.startswith(screenshots_dir):
4424 unnecessary_screenshots.append(png_path)
4425
4426 for added_id in added_ids:
4427 _CheckScreenshotAdded(screenshots_dir, added_id)
4428
4429 for modified_id in modified_ids:
4430 _CheckScreenshotAdded(screenshots_dir, modified_id)
4431
4432 for removed_id in removed_ids:
4433 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4434
4435 results = []
4436 if unnecessary_screenshots:
4437 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394438 'Do not include actual screenshots in the changelist. Run '
4439 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144440 sorted(unnecessary_screenshots)))
4441
4442 if missing_sha1:
4443 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394444 'You are adding or modifying UI strings.\n'
4445 'To ensure the best translations, take screenshots of the relevant UI '
4446 '(https://g.co/chrome/translation) and add these files to your '
4447 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144448
4449 if unnecessary_sha1_files:
4450 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394451 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144452 sorted(unnecessary_sha1_files)))
4453
4454 return results