blob: 9736ebf1489fc01c94e6728ea46ad9d3028d8975 [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 (
Egor Paskoce145c42018-09-28 19:31:04526 r"^ui[\\/]gl[\\/].*\.cc$",
527 r"^media[\\/]gpu[\\/].*\.cc$",
528 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53529 ),
530 ),
531 (
Dave Tapuska98199b612019-07-10 13:30:44532 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20533 (
thomasanderson11aa41d2017-06-08 22:22:38534 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20535 ),
536 True,
537 (
Egor Paskoce145c42018-09-28 19:31:04538 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
539 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
540 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20541 ),
542 ),
543 (
tomhudsone2c14d552016-05-26 17:07:46544 'setMatrixClip',
545 (
546 'Overriding setMatrixClip() is prohibited; ',
547 'the base function is deprecated. ',
548 ),
549 True,
550 (),
551 ),
552 (
[email protected]52657f62013-05-20 05:30:31553 'SkRefPtr',
554 (
555 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22556 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31557 ),
558 True,
559 (),
560 ),
561 (
562 'SkAutoRef',
563 (
564 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22565 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31566 ),
567 True,
568 (),
569 ),
570 (
571 'SkAutoTUnref',
572 (
573 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22574 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31575 ),
576 True,
577 (),
578 ),
579 (
580 'SkAutoUnref',
581 (
582 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
583 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22584 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31585 ),
586 True,
587 (),
588 ),
[email protected]d89eec82013-12-03 14:10:59589 (
590 r'/HANDLE_EINTR\(.*close',
591 (
592 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
593 'descriptor will be closed, and it is incorrect to retry the close.',
594 'Either call close directly and ignore its return value, or wrap close',
595 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
596 ),
597 True,
598 (),
599 ),
600 (
601 r'/IGNORE_EINTR\((?!.*close)',
602 (
603 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
604 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
605 ),
606 True,
607 (
608 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04609 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
610 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59611 ),
612 ),
[email protected]ec5b3f02014-04-04 18:43:43613 (
614 r'/v8::Extension\(',
615 (
616 'Do not introduce new v8::Extensions into the code base, use',
617 'gin::Wrappable instead. See http://crbug.com/334679',
618 ),
619 True,
[email protected]f55c90ee62014-04-12 00:50:03620 (
Egor Paskoce145c42018-09-28 19:31:04621 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03622 ),
[email protected]ec5b3f02014-04-04 18:43:43623 ),
skyostilf9469f72015-04-20 10:38:52624 (
jame2d1a952016-04-02 00:27:10625 '#pragma comment(lib,',
626 (
627 'Specify libraries to link with in build files and not in the source.',
628 ),
629 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41630 (
tzik3f295992018-12-04 20:32:23631 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04632 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41633 ),
jame2d1a952016-04-02 00:27:10634 ),
fdorayc4ac18d2017-05-01 21:39:59635 (
Gabriel Charette7cc6c432018-04-25 20:52:02636 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59637 (
638 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
639 ),
640 False,
641 (),
642 ),
643 (
Gabriel Charette7cc6c432018-04-25 20:52:02644 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59645 (
646 'Consider using THREAD_CHECKER macros instead of the class directly.',
647 ),
648 False,
649 (),
650 ),
dbeamb6f4fde2017-06-15 04:03:06651 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06652 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
653 (
654 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
655 'deprecated (http://crbug.com/634507). Please avoid converting away',
656 'from the Time types in Chromium code, especially if any math is',
657 'being done on time values. For interfacing with platform/library',
658 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
659 'type converter methods instead. For faking TimeXXX values (for unit',
660 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
661 'other use cases, please contact base/time/OWNERS.',
662 ),
663 False,
664 (),
665 ),
666 (
dbeamb6f4fde2017-06-15 04:03:06667 'CallJavascriptFunctionUnsafe',
668 (
669 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
670 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
671 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
672 ),
673 False,
674 (
Egor Paskoce145c42018-09-28 19:31:04675 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
676 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
677 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06678 ),
679 ),
dskiba1474c2bfd62017-07-20 02:19:24680 (
681 'leveldb::DB::Open',
682 (
683 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
684 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
685 "Chrome's tracing, making their memory usage visible.",
686 ),
687 True,
688 (
689 r'^third_party/leveldatabase/.*\.(cc|h)$',
690 ),
Gabriel Charette0592c3a2017-07-26 12:02:04691 ),
692 (
Chris Mumfordc38afb62017-10-09 17:55:08693 'leveldb::NewMemEnv',
694 (
695 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58696 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
697 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08698 ),
699 True,
700 (
701 r'^third_party/leveldatabase/.*\.(cc|h)$',
702 ),
703 ),
704 (
Gabriel Charetted9839bc2017-07-29 14:17:47705 'RunLoop::QuitCurrent',
706 (
Robert Liao64b7ab22017-08-04 23:03:43707 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
708 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47709 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41710 False,
Gabriel Charetted9839bc2017-07-29 14:17:47711 (),
Gabriel Charettea44975052017-08-21 23:14:04712 ),
713 (
714 'base::ScopedMockTimeMessageLoopTaskRunner',
715 (
Gabriel Charette87cc1af2018-04-25 20:52:51716 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charette21a47f0132019-07-16 16:47:20717 'ScopedTaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51718 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
719 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
720 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04721 ),
Gabriel Charette87cc1af2018-04-25 20:52:51722 False,
Gabriel Charettea44975052017-08-21 23:14:04723 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57724 ),
725 (
Dave Tapuska98199b612019-07-10 13:30:44726 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57727 (
728 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02729 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57730 ),
731 True,
732 (),
Francois Doray43670e32017-09-27 12:40:38733 ),
734 (
Peter Kasting991618a62019-06-17 22:00:09735 r'/\bstd::stoi\b',
736 (
737 'std::stoi uses exceptions to communicate results. ',
738 'Use base::StringToInt() instead.',
739 ),
740 True,
741 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
742 ),
743 (
744 r'/\bstd::stol\b',
745 (
746 'std::stol uses exceptions to communicate results. ',
747 'Use base::StringToInt() instead.',
748 ),
749 True,
750 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
751 ),
752 (
753 r'/\bstd::stoul\b',
754 (
755 'std::stoul uses exceptions to communicate results. ',
756 'Use base::StringToUint() instead.',
757 ),
758 True,
759 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
760 ),
761 (
762 r'/\bstd::stoll\b',
763 (
764 'std::stoll uses exceptions to communicate results. ',
765 'Use base::StringToInt64() instead.',
766 ),
767 True,
768 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
769 ),
770 (
771 r'/\bstd::stoull\b',
772 (
773 'std::stoull uses exceptions to communicate results. ',
774 'Use base::StringToUint64() instead.',
775 ),
776 True,
777 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
778 ),
779 (
780 r'/\bstd::stof\b',
781 (
782 'std::stof uses exceptions to communicate results. ',
783 'For locale-independent values, e.g. reading numbers from disk',
784 'profiles, use base::StringToDouble().',
785 'For user-visible values, parse using ICU.',
786 ),
787 True,
788 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
789 ),
790 (
791 r'/\bstd::stod\b',
792 (
793 'std::stod uses exceptions to communicate results. ',
794 'For locale-independent values, e.g. reading numbers from disk',
795 'profiles, use base::StringToDouble().',
796 'For user-visible values, parse using ICU.',
797 ),
798 True,
799 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
800 ),
801 (
802 r'/\bstd::stold\b',
803 (
804 'std::stold uses exceptions to communicate results. ',
805 'For locale-independent values, e.g. reading numbers from disk',
806 'profiles, use base::StringToDouble().',
807 'For user-visible values, parse using ICU.',
808 ),
809 True,
810 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
811 ),
812 (
Daniel Bratell69334cc2019-03-26 11:07:45813 r'/\bstd::to_string\b',
814 (
815 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09816 'For locale-independent strings, e.g. writing numbers to disk',
817 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45818 'For user-visible strings, use base::FormatNumber() and',
819 'the related functions in base/i18n/number_formatting.h.',
820 ),
Peter Kasting991618a62019-06-17 22:00:09821 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21822 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45823 ),
824 (
825 r'/\bstd::shared_ptr\b',
826 (
827 'std::shared_ptr should not be used. Use scoped_refptr instead.',
828 ),
829 True,
Daniel Bratell609102be2019-03-27 20:53:21830 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
831 ),
832 (
Peter Kasting991618a62019-06-17 22:00:09833 r'/\bstd::weak_ptr\b',
834 (
835 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
836 ),
837 True,
838 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
839 ),
840 (
Daniel Bratell609102be2019-03-27 20:53:21841 r'/\blong long\b',
842 (
843 'long long is banned. Use stdint.h if you need a 64 bit number.',
844 ),
845 False, # Only a warning since it is already used.
846 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
847 ),
848 (
849 r'/\bstd::bind\b',
850 (
851 'std::bind is banned because of lifetime risks.',
852 'Use base::BindOnce or base::BindRepeating instead.',
853 ),
854 True,
855 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
856 ),
857 (
858 r'/\b#include <chrono>\b',
859 (
860 '<chrono> overlaps with Time APIs in base. Keep using',
861 'base classes.',
862 ),
863 True,
864 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
865 ),
866 (
867 r'/\b#include <exception>\b',
868 (
869 'Exceptions are banned and disabled in Chromium.',
870 ),
871 True,
872 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
873 ),
874 (
875 r'/\bstd::function\b',
876 (
877 'std::function is banned. Instead use base::Callback which directly',
878 'supports Chromium\'s weak pointers, ref counting and more.',
879 ),
Peter Kasting991618a62019-06-17 22:00:09880 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21881 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
882 ),
883 (
884 r'/\b#include <random>\b',
885 (
886 'Do not use any random number engines from <random>. Instead',
887 'use base::RandomBitGenerator.',
888 ),
889 True,
890 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
891 ),
892 (
893 r'/\bstd::ratio\b',
894 (
895 'std::ratio is banned by the Google Style Guide.',
896 ),
897 True,
898 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45899 ),
900 (
Francois Doray43670e32017-09-27 12:40:38901 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
902 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
903 (
904 'Use the new API in base/threading/thread_restrictions.h.',
905 ),
Gabriel Charette04b138f2018-08-06 00:03:22906 False,
Francois Doray43670e32017-09-27 12:40:38907 (),
908 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38909 (
danakj7a2b7082019-05-21 21:13:51910 r'/\bbase::Bind\(',
911 (
912 'Please use base::Bind{Once,Repeating} instead',
913 'of base::Bind. (crbug.com/714018)',
914 ),
915 False,
916 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
917 ),
918 (
919 r'/\bbase::Callback[<:]',
920 (
921 'Please use base::{Once,Repeating}Callback instead',
922 'of base::Callback. (crbug.com/714018)',
923 ),
924 False,
925 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
926 ),
927 (
928 r'/\bbase::Closure\b',
929 (
930 'Please use base::{Once,Repeating}Closure instead',
931 'of base::Closure. (crbug.com/714018)',
932 ),
933 False,
934 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
935 ),
936 (
Alex Ilin5929abe32019-04-03 17:09:34937 r'/base::SharedMemory(|Handle)',
Alex Ilin63058f62019-03-28 19:29:45938 (
939 'base::SharedMemory is deprecated. Please use',
940 '{Writable,ReadOnly}SharedMemoryRegion instead.',
941 ),
942 False,
943 (),
944 ),
945 (
Michael Giuffrida7f93d6922019-04-19 14:39:58946 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19947 (
948 'RunMessageLoop is deprecated, use RunLoop instead.',
949 ),
950 False,
951 (),
952 ),
953 (
Dave Tapuska98199b612019-07-10 13:30:44954 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19955 (
956 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
957 ),
958 False,
959 (),
960 ),
961 (
Dave Tapuska98199b612019-07-10 13:30:44962 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19963 (
964 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
965 "if you're convinced you need this.",
966 ),
967 False,
968 (),
969 ),
970 (
Dave Tapuska98199b612019-07-10 13:30:44971 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19972 (
973 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
974 'BrowserThread::UI, TestBrowserThreadBundle::RunIOThreadUntilIdle',
975 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
976 'async events instead of flushing threads.',
977 ),
978 False,
979 (),
980 ),
981 (
982 r'MessageLoopRunner',
983 (
984 'MessageLoopRunner is deprecated, use RunLoop instead.',
985 ),
986 False,
987 (),
988 ),
989 (
Dave Tapuska98199b612019-07-10 13:30:44990 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19991 (
992 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
993 "gab@ if you found a use case where this is the only solution.",
994 ),
995 False,
996 (),
997 ),
998 (
Victor Costane48a2e82019-03-15 22:02:34999 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161000 (
Victor Costane48a2e82019-03-15 22:02:341001 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161002 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1003 ),
1004 True,
1005 (
1006 r'^sql/initialization\.(cc|h)$',
1007 r'^third_party/sqlite/.*\.(c|cc|h)$',
1008 ),
1009 ),
Matt Menke7f520a82018-03-28 21:38:371010 (
1011 'net::URLFetcher',
1012 (
1013 'net::URLFetcher should no longer be used in content embedders. ',
1014 'Instead, use network::SimpleURLLoader instead, which supports ',
1015 'an out-of-process network stack. ',
1016 'net::URLFetcher may still be used in binaries that do not embed',
1017 'content.',
1018 ),
Matt Menke59716d02018-04-05 12:45:531019 False,
Matt Menke7f520a82018-03-28 21:38:371020 (
Egor Paskoce145c42018-09-28 19:31:041021 r'^ios[\\/].*\.(cc|h)$',
1022 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:371023 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:041024 r'^net[\\/].*\.(cc|h)$',
1025 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi347f6992019-07-11 00:29:201026 r'^fuchsia/engine/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:371027 ),
1028 ),
jdoerried7d10ab2018-04-27 10:46:131029 (
Dave Tapuska98199b612019-07-10 13:30:441030 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471031 (
1032 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1033 'base::RandomShuffle instead.'
1034 ),
1035 True,
1036 (),
1037 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241038 (
1039 'ios/web/public/test/http_server',
1040 (
1041 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1042 ),
1043 False,
1044 (),
1045 ),
Robert Liao764c9492019-01-24 18:46:281046 (
1047 'GetAddressOf',
1048 (
1049 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
1050 'implicated in a few leaks. Use operator& instead.'
1051 ),
1052 True,
1053 (),
1054 ),
Antonio Gomes07300d02019-03-13 20:59:571055 (
1056 'DEFINE_TYPE_CASTS',
1057 (
1058 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1059 '//third_party/blink/renderer/platform/casting.h.'
1060 ),
1061 True,
1062 (
1063 r'^third_party/blink/renderer/.*\.(cc|h)$',
1064 ),
1065 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381066 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371067 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381068 (
1069 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1070 ),
1071 True,
1072 (),
1073 ),
Ben Lewisa9514602019-04-29 17:53:051074 (
1075 'SHFileOperation',
1076 (
1077 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1078 'complex functions to achieve the same goals. Use IFileOperation for ',
1079 'any esoteric actions instead.'
1080 ),
1081 True,
1082 (),
1083 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181084 (
Cliff Smolinsky81951642019-04-30 21:39:511085 'StringFromGUID2',
1086 (
1087 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1088 'Use base::win::String16FromGUID instead.'
1089 ),
1090 True,
1091 (
1092 r'/base/win/win_util_unittest.cc'
1093 ),
1094 ),
1095 (
1096 'StringFromCLSID',
1097 (
1098 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1099 'Use base::win::String16FromGUID instead.'
1100 ),
1101 True,
1102 (
1103 r'/base/win/win_util_unittest.cc'
1104 ),
1105 ),
1106 (
Avi Drissman7382afa02019-04-29 23:27:131107 'kCFAllocatorNull',
1108 (
1109 'The use of kCFAllocatorNull with the NoCopy creation of ',
1110 'CoreFoundation types is prohibited.',
1111 ),
1112 True,
1113 (),
1114 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291115 (
1116 'mojo::ConvertTo',
1117 (
1118 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1119 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1120 'StringTraits if you would like to convert between custom types and',
1121 'the wire format of mojom types.'
1122 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221123 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291124 (
1125 r'^third_party/blink/.*\.(cc|h)$',
1126 r'^content/renderer/.*\.(cc|h)$',
1127 ),
1128 ),
[email protected]127f18ec2012-06-16 05:05:591129)
1130
wnwenbdc444e2016-05-25 13:44:151131
mlamouria82272622014-09-16 18:45:041132_IPC_ENUM_TRAITS_DEPRECATED = (
1133 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501134 'See http://www.chromium.org/Home/chromium-security/education/'
1135 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041136
Stephen Martinis97a394142018-06-07 23:06:051137_LONG_PATH_ERROR = (
1138 'Some files included in this CL have file names that are too long (> 200'
1139 ' characters). If committed, these files will cause issues on Windows. See'
1140 ' https://crbug.com/612667 for more details.'
1141)
1142
Shenghua Zhangbfaa38b82017-11-16 21:58:021143_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041144 r".*[\\/]BuildHooksAndroidImpl\.java",
1145 r".*[\\/]LicenseContentProvider\.java",
1146 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281147 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021148]
[email protected]127f18ec2012-06-16 05:05:591149
Sean Kau46e29bc2017-08-28 16:31:161150# These paths contain test data and other known invalid JSON files.
1151_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041152 r'test[\\/]data[\\/]',
1153 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1154 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041155 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431156 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161157]
1158
1159
[email protected]b00342e7f2013-03-26 16:21:541160_VALID_OS_MACROS = (
1161 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081162 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541163 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121164 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541165 'OS_BSD',
1166 'OS_CAT', # For testing.
1167 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041168 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541169 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371170 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541171 'OS_IOS',
1172 'OS_LINUX',
1173 'OS_MACOSX',
1174 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211175 'OS_NACL_NONSFI',
1176 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121177 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541178 'OS_OPENBSD',
1179 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371180 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541181 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541182 'OS_WIN',
1183)
1184
1185
agrievef32bcc72016-04-04 14:57:401186_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391187 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361188 'base/android/jni_generator/jni_generator.pydeps',
1189 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221190 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361191 'build/android/gyp/aar.pydeps',
1192 'build/android/gyp/aidl.pydeps',
1193 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381194 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361195 'build/android/gyp/bytecode_processor.pydeps',
1196 'build/android/gyp/compile_resources.pydeps',
Andrew Grievef89e926c2019-02-07 18:36:571197 'build/android/gyp/create_app_bundle_minimal_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361198 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1199 'build/android/gyp/copy_ex.pydeps',
1200 'build/android/gyp/create_app_bundle.pydeps',
1201 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361202 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221203 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361204 'build/android/gyp/create_tool_wrapper.pydeps',
1205 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591206 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361207 'build/android/gyp/dex.pydeps',
1208 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361209 'build/android/gyp/filter_zip.pydeps',
1210 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361211 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361212 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581213 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361214 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261215 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361216 'build/android/gyp/javac.pydeps',
1217 'build/android/gyp/jinja_template.pydeps',
1218 'build/android/gyp/lint.pydeps',
1219 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361220 'build/android/gyp/merge_manifest.pydeps',
1221 'build/android/gyp/prepare_resources.pydeps',
1222 'build/android/gyp/proguard.pydeps',
1223 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461224 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561225 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361226 'build/android/incremental_install/generate_android_manifest.pydeps',
1227 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221228 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401229 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041230 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361231 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411232 'chrome/android/features/create_stripped_java_factory.pydeps',
agrieve732db3a2016-04-26 19:18:191233 'net/tools/testserver/testserver.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021234 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401235]
1236
wnwenbdc444e2016-05-25 13:44:151237
agrievef32bcc72016-04-04 14:57:401238_GENERIC_PYDEPS_FILES = [
John Chencde89192018-01-27 21:18:401239 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Cole Winstanley7045a1b2018-08-27 23:37:291240 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
John Budorickbc3571aa2019-04-25 02:20:061241 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221242 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401243]
1244
wnwenbdc444e2016-05-25 13:44:151245
agrievef32bcc72016-04-04 14:57:401246_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1247
1248
Eric Boren6fd2b932018-01-25 15:05:081249# Bypass the AUTHORS check for these accounts.
1250_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291251 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1252 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081253 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321254 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591255 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451256 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591257 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221258 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041259 ) | set('%[email protected]' % s
1260 for s in ('chromium-autoroll',)
1261 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301262 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081263
1264
Daniel Bratell65b033262019-04-23 08:17:061265def _IsCPlusPlusFile(input_api, file_path):
1266 """Returns True if this file contains C++-like code (and not Python,
1267 Go, Java, MarkDown, ...)"""
1268
1269 ext = input_api.os_path.splitext(file_path)[1]
1270 # This list is compatible with CppChecker.IsCppFile but we should
1271 # consider adding ".c" to it. If we do that we can use this function
1272 # at more places in the code.
1273 return ext in (
1274 '.h',
1275 '.cc',
1276 '.cpp',
1277 '.m',
1278 '.mm',
1279 )
1280
1281def _IsCPlusPlusHeaderFile(input_api, file_path):
1282 return input_api.os_path.splitext(file_path)[1] == ".h"
1283
1284
1285def _IsJavaFile(input_api, file_path):
1286 return input_api.os_path.splitext(file_path)[1] == ".java"
1287
1288
1289def _IsProtoFile(input_api, file_path):
1290 return input_api.os_path.splitext(file_path)[1] == ".proto"
1291
[email protected]55459852011-08-10 15:17:191292def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1293 """Attempts to prevent use of functions intended only for testing in
1294 non-testing code. For now this is just a best-effort implementation
1295 that ignores header files and may have some false positives. A
1296 better implementation would probably need a proper C++ parser.
1297 """
1298 # We only scan .cc files and the like, as the declaration of
1299 # for-testing functions in header files are hard to distinguish from
1300 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491301 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191302
jochenc0d4808c2015-07-27 09:25:421303 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191304 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091305 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191306 exclusion_pattern = input_api.re.compile(
1307 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1308 base_function_pattern, base_function_pattern))
1309
1310 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441311 black_list = (_EXCLUDED_PATHS +
1312 _TEST_CODE_EXCLUDED_PATHS +
1313 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191314 return input_api.FilterSourceFile(
1315 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491316 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191317 black_list=black_list)
1318
1319 problems = []
1320 for f in input_api.AffectedSourceFiles(FilterFile):
1321 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241322 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031323 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461324 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031325 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191326 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031327 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191328
1329 if problems:
[email protected]f7051d52013-04-02 18:31:421330 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031331 else:
1332 return []
[email protected]55459852011-08-10 15:17:191333
1334
Vaclav Brozek7dbc28c2018-03-27 08:35:231335def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1336 """This is a simplified version of
1337 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1338 """
1339 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1340 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1341 name_pattern = r'ForTest(s|ing)?'
1342 # Describes an occurrence of "ForTest*" inside a // comment.
1343 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1344 # Catch calls.
1345 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1346 # Ignore definitions. (Comments are ignored separately.)
1347 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1348
1349 problems = []
1350 sources = lambda x: input_api.FilterSourceFile(
1351 x,
1352 black_list=(('(?i).*test', r'.*\/junit\/')
1353 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491354 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231355 )
1356 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1357 local_path = f.LocalPath()
1358 is_inside_javadoc = False
1359 for line_number, line in f.ChangedContents():
1360 if is_inside_javadoc and javadoc_end_re.search(line):
1361 is_inside_javadoc = False
1362 if not is_inside_javadoc and javadoc_start_re.search(line):
1363 is_inside_javadoc = True
1364 if is_inside_javadoc:
1365 continue
1366 if (inclusion_re.search(line) and
1367 not comment_re.search(line) and
1368 not exclusion_re.search(line)):
1369 problems.append(
1370 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1371
1372 if problems:
1373 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1374 else:
1375 return []
1376
1377
[email protected]10689ca2011-09-02 02:31:541378def _CheckNoIOStreamInHeaders(input_api, output_api):
1379 """Checks to make sure no .h files include <iostream>."""
1380 files = []
1381 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1382 input_api.re.MULTILINE)
1383 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1384 if not f.LocalPath().endswith('.h'):
1385 continue
1386 contents = input_api.ReadFile(f)
1387 if pattern.search(contents):
1388 files.append(f)
1389
1390 if len(files):
yolandyandaabc6d2016-04-18 18:29:391391 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061392 'Do not #include <iostream> in header files, since it inserts static '
1393 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541394 '#include <ostream>. See http://crbug.com/94794',
1395 files) ]
1396 return []
1397
Danil Chapovalov3518f362018-08-11 16:13:431398def _CheckNoStrCatRedefines(input_api, output_api):
1399 """Checks no windows headers with StrCat redefined are included directly."""
1400 files = []
1401 pattern_deny = input_api.re.compile(
1402 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1403 input_api.re.MULTILINE)
1404 pattern_allow = input_api.re.compile(
1405 r'^#include\s"base/win/windows_defines.inc"',
1406 input_api.re.MULTILINE)
1407 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1408 contents = input_api.ReadFile(f)
1409 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1410 files.append(f.LocalPath())
1411
1412 if len(files):
1413 return [output_api.PresubmitError(
1414 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1415 'directly since they pollute code with StrCat macro. Instead, '
1416 'include matching header from base/win. See http://crbug.com/856536',
1417 files) ]
1418 return []
1419
[email protected]10689ca2011-09-02 02:31:541420
[email protected]72df4e782012-06-21 16:28:181421def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521422 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181423 problems = []
1424 for f in input_api.AffectedFiles():
1425 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1426 continue
1427
1428 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041429 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181430 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1431
1432 if not problems:
1433 return []
1434 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1435 '\n'.join(problems))]
1436
Dominic Battre033531052018-09-24 15:45:341437def _CheckNoDISABLETypoInTests(input_api, output_api):
1438 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1439
1440 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1441 instead of DISABLED_. To filter false positives, reports are only generated
1442 if a corresponding MAYBE_ line exists.
1443 """
1444 problems = []
1445
1446 # The following two patterns are looked for in tandem - is a test labeled
1447 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1448 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1449 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1450
1451 # This is for the case that a test is disabled on all platforms.
1452 full_disable_pattern = input_api.re.compile(
1453 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1454 input_api.re.MULTILINE)
1455
Katie Df13948e2018-09-25 07:33:441456 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341457 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1458 continue
1459
1460 # Search for MABYE_, DISABLE_ pairs.
1461 disable_lines = {} # Maps of test name to line number.
1462 maybe_lines = {}
1463 for line_num, line in f.ChangedContents():
1464 disable_match = disable_pattern.search(line)
1465 if disable_match:
1466 disable_lines[disable_match.group(1)] = line_num
1467 maybe_match = maybe_pattern.search(line)
1468 if maybe_match:
1469 maybe_lines[maybe_match.group(1)] = line_num
1470
1471 # Search for DISABLE_ occurrences within a TEST() macro.
1472 disable_tests = set(disable_lines.keys())
1473 maybe_tests = set(maybe_lines.keys())
1474 for test in disable_tests.intersection(maybe_tests):
1475 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1476
1477 contents = input_api.ReadFile(f)
1478 full_disable_match = full_disable_pattern.search(contents)
1479 if full_disable_match:
1480 problems.append(' %s' % f.LocalPath())
1481
1482 if not problems:
1483 return []
1484 return [
1485 output_api.PresubmitPromptWarning(
1486 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1487 '\n'.join(problems))
1488 ]
1489
[email protected]72df4e782012-06-21 16:28:181490
danakj61c1aa22015-10-26 19:55:521491def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571492 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521493 errors = []
1494 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1495 input_api.re.MULTILINE)
1496 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1497 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1498 continue
1499 for lnum, line in f.ChangedContents():
1500 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171501 errors.append(output_api.PresubmitError(
1502 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571503 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171504 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521505 return errors
1506
1507
Makoto Shimazu3ad422cd2019-05-08 02:35:141508def _FindHistogramNameInChunk(histogram_name, chunk):
1509 """Tries to find a histogram name or prefix in a line.
1510
1511 Returns the existence of the histogram name, or None if it needs more chunk
1512 to determine."""
mcasasb7440c282015-02-04 14:52:191513 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1514 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141515 if '<affected-histogram' in chunk:
1516 # If the tag is not completed, needs more chunk to get the name.
1517 if not '>' in chunk:
1518 return None
1519 if not 'name="' in chunk:
1520 return False
1521 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1522 # expect the only attribute is the name.
1523 histogram_prefix = chunk.split('"')[1]
1524 return histogram_prefix in histogram_name
1525 # Typically the whole histogram name should in the line.
1526 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191527
1528
1529def _CheckUmaHistogramChanges(input_api, output_api):
1530 """Check that UMA histogram names in touched lines can still be found in other
1531 lines of the patch or in histograms.xml. Note that this check would not catch
1532 the reverse: changes in histograms.xml not matched in the code itself."""
1533 touched_histograms = []
1534 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471535 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1536 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1537 name_pattern = r'"(.*?)"'
1538 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1539 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1540 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1541 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1542 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171543 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191544 for f in input_api.AffectedFiles():
1545 # If histograms.xml itself is modified, keep the modified lines for later.
1546 if f.LocalPath().endswith(('histograms.xml')):
1547 histograms_xml_modifications = f.ChangedContents()
1548 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471549 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1550 single_line_re = single_line_c_re
1551 split_line_prefix_re = split_line_c_prefix_re
1552 elif f.LocalPath().endswith(('java')):
1553 single_line_re = single_line_java_re
1554 split_line_prefix_re = split_line_java_prefix_re
1555 else:
mcasasb7440c282015-02-04 14:52:191556 continue
1557 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171558 if last_line_matched_prefix:
1559 suffix_found = split_line_suffix_re.search(line)
1560 if suffix_found :
1561 touched_histograms.append([suffix_found.group(1), f, line_num])
1562 last_line_matched_prefix = False
1563 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061564 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191565 if found:
1566 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171567 continue
1568 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191569
1570 # Search for the touched histogram names in the local modifications to
1571 # histograms.xml, and, if not found, on the base histograms.xml file.
1572 unmatched_histograms = []
1573 for histogram_info in touched_histograms:
1574 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141575 chunk = ''
mcasasb7440c282015-02-04 14:52:191576 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141577 chunk += line
1578 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1579 if histogram_name_found is None:
1580 continue
1581 chunk = ''
mcasasb7440c282015-02-04 14:52:191582 if histogram_name_found:
1583 break
1584 if not histogram_name_found:
1585 unmatched_histograms.append(histogram_info)
1586
eromanb90c82e7e32015-04-01 15:13:491587 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191588 problems = []
1589 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491590 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191591 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451592 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191593 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141594 chunk = ''
mcasasb7440c282015-02-04 14:52:191595 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141596 chunk += line
1597 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1598 chunk)
1599 if histogram_name_found is None:
1600 continue
1601 chunk = ''
mcasasb7440c282015-02-04 14:52:191602 if histogram_name_found:
1603 break
1604 if not histogram_name_found:
1605 problems.append(' [%s:%d] %s' %
1606 (f.LocalPath(), line_num, histogram_name))
1607
1608 if not problems:
1609 return []
1610 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1611 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491612 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191613
wnwenbdc444e2016-05-25 13:44:151614
yolandyandaabc6d2016-04-18 18:29:391615def _CheckFlakyTestUsage(input_api, output_api):
1616 """Check that FlakyTest annotation is our own instead of the android one"""
1617 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1618 files = []
1619 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1620 if f.LocalPath().endswith('Test.java'):
1621 if pattern.search(input_api.ReadFile(f)):
1622 files.append(f)
1623 if len(files):
1624 return [output_api.PresubmitError(
1625 'Use org.chromium.base.test.util.FlakyTest instead of '
1626 'android.test.FlakyTest',
1627 files)]
1628 return []
mcasasb7440c282015-02-04 14:52:191629
wnwenbdc444e2016-05-25 13:44:151630
[email protected]8ea5d4b2011-09-13 21:49:221631def _CheckNoNewWStrings(input_api, output_api):
1632 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271633 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221634 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201635 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571636 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341637 '/win/' in f.LocalPath() or
1638 'chrome_elf' in f.LocalPath() or
1639 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201640 continue
[email protected]8ea5d4b2011-09-13 21:49:221641
[email protected]a11dbe9b2012-08-07 01:32:581642 allowWString = False
[email protected]b5c24292011-11-28 14:38:201643 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581644 if 'presubmit: allow wstring' in line:
1645 allowWString = True
1646 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271647 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581648 allowWString = False
1649 else:
1650 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221651
[email protected]55463aa62011-10-12 00:48:271652 if not problems:
1653 return []
1654 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581655 ' If you are calling a cross-platform API that accepts a wstring, '
1656 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271657 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221658
1659
[email protected]2a8ac9c2011-10-19 17:20:441660def _CheckNoDEPSGIT(input_api, output_api):
1661 """Make sure .DEPS.git is never modified manually."""
1662 if any(f.LocalPath().endswith('.DEPS.git') for f in
1663 input_api.AffectedFiles()):
1664 return [output_api.PresubmitError(
1665 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1666 'automated system based on what\'s in DEPS and your changes will be\n'
1667 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501668 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1669 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441670 'for more information')]
1671 return []
1672
1673
tandriief664692014-09-23 14:51:471674def _CheckValidHostsInDEPS(input_api, output_api):
1675 """Checks that DEPS file deps are from allowed_hosts."""
1676 # Run only if DEPS file has been modified to annoy fewer bystanders.
1677 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1678 return []
1679 # Outsource work to gclient verify
1680 try:
John Budorickf20c0042019-04-25 23:23:401681 gclient_path = input_api.os_path.join(
1682 input_api.PresubmitLocalPath(),
1683 'third_party', 'depot_tools', 'gclient.py')
1684 input_api.subprocess.check_output(
1685 [input_api.python_executable, gclient_path, 'verify'],
1686 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471687 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201688 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471689 return [output_api.PresubmitError(
1690 'DEPS file must have only git dependencies.',
1691 long_text=error.output)]
1692
1693
[email protected]127f18ec2012-06-16 05:05:591694def _CheckNoBannedFunctions(input_api, output_api):
1695 """Make sure that banned functions are not used."""
1696 warnings = []
1697 errors = []
1698
wnwenbdc444e2016-05-25 13:44:151699 def IsBlacklisted(affected_file, blacklist):
1700 local_path = affected_file.LocalPath()
1701 for item in blacklist:
1702 if input_api.re.match(item, local_path):
1703 return True
1704 return False
1705
Peter K. Lee6c03ccff2019-07-15 14:40:051706 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541707 local_path = affected_file.LocalPath()
1708 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1709 return False
1710 basename = input_api.os_path.basename(local_path)
1711 if 'ios' in basename.split('_'):
1712 return True
1713 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1714 if sep and 'ios' in local_path.split(sep):
1715 return True
1716 return False
1717
wnwenbdc444e2016-05-25 13:44:151718 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
1719 matched = False
1720 if func_name[0:1] == '/':
1721 regex = func_name[1:]
1722 if input_api.re.search(regex, line):
1723 matched = True
1724 elif func_name in line:
dchenge07de812016-06-20 19:27:171725 matched = True
wnwenbdc444e2016-05-25 13:44:151726 if matched:
dchenge07de812016-06-20 19:27:171727 problems = warnings
wnwenbdc444e2016-05-25 13:44:151728 if error:
dchenge07de812016-06-20 19:27:171729 problems = errors
wnwenbdc444e2016-05-25 13:44:151730 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
1731 for message_line in message:
1732 problems.append(' %s' % message_line)
1733
Eric Stevensona9a980972017-09-23 00:04:411734 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1735 for f in input_api.AffectedFiles(file_filter=file_filter):
1736 for line_num, line in f.ChangedContents():
1737 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1738 CheckForMatch(f, line_num, line, func_name, message, error)
1739
[email protected]127f18ec2012-06-16 05:05:591740 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1741 for f in input_api.AffectedFiles(file_filter=file_filter):
1742 for line_num, line in f.ChangedContents():
1743 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151744 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591745
Peter K. Lee6c03ccff2019-07-15 14:40:051746 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541747 for line_num, line in f.ChangedContents():
1748 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1749 CheckForMatch(f, line_num, line, func_name, message, error)
1750
Peter K. Lee6c03ccff2019-07-15 14:40:051751 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1752 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1753 for line_num, line in f.ChangedContents():
1754 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1755 CheckForMatch(f, line_num, line, func_name, message, error)
1756
[email protected]127f18ec2012-06-16 05:05:591757 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1758 for f in input_api.AffectedFiles(file_filter=file_filter):
1759 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491760 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491761 if IsBlacklisted(f, excluded_paths):
1762 continue
wnwenbdc444e2016-05-25 13:44:151763 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591764
1765 result = []
1766 if (warnings):
1767 result.append(output_api.PresubmitPromptWarning(
1768 'Banned functions were used.\n' + '\n'.join(warnings)))
1769 if (errors):
1770 result.append(output_api.PresubmitError(
1771 'Banned functions were used.\n' + '\n'.join(errors)))
1772 return result
1773
1774
[email protected]6c063c62012-07-11 19:11:061775def _CheckNoPragmaOnce(input_api, output_api):
1776 """Make sure that banned functions are not used."""
1777 files = []
1778 pattern = input_api.re.compile(r'^#pragma\s+once',
1779 input_api.re.MULTILINE)
1780 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1781 if not f.LocalPath().endswith('.h'):
1782 continue
1783 contents = input_api.ReadFile(f)
1784 if pattern.search(contents):
1785 files.append(f)
1786
1787 if files:
1788 return [output_api.PresubmitError(
1789 'Do not use #pragma once in header files.\n'
1790 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1791 files)]
1792 return []
1793
[email protected]127f18ec2012-06-16 05:05:591794
[email protected]e7479052012-09-19 00:26:121795def _CheckNoTrinaryTrueFalse(input_api, output_api):
1796 """Checks to make sure we don't introduce use of foo ? true : false."""
1797 problems = []
1798 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1799 for f in input_api.AffectedFiles():
1800 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1801 continue
1802
1803 for line_num, line in f.ChangedContents():
1804 if pattern.match(line):
1805 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1806
1807 if not problems:
1808 return []
1809 return [output_api.PresubmitPromptWarning(
1810 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1811 '\n'.join(problems))]
1812
1813
[email protected]55f9f382012-07-31 11:02:181814def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281815 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181816 change. Breaking - rules is an error, breaking ! rules is a
1817 warning.
1818 """
mohan.reddyf21db962014-10-16 12:26:471819 import sys
[email protected]55f9f382012-07-31 11:02:181820 # We need to wait until we have an input_api object and use this
1821 # roundabout construct to import checkdeps because this file is
1822 # eval-ed and thus doesn't have __file__.
1823 original_sys_path = sys.path
1824 try:
1825 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471826 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181827 import checkdeps
[email protected]55f9f382012-07-31 11:02:181828 from rules import Rule
1829 finally:
1830 # Restore sys.path to what it was before.
1831 sys.path = original_sys_path
1832
1833 added_includes = []
rhalavati08acd232017-04-03 07:23:281834 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241835 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181836 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:061837 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501838 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081839 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061840 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501841 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081842 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061843 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501844 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081845 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181846
[email protected]26385172013-05-09 23:11:351847 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181848
1849 error_descriptions = []
1850 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:281851 error_subjects = set()
1852 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:181853 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
1854 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:081855 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:181856 description_with_path = '%s\n %s' % (path, rule_description)
1857 if rule_type == Rule.DISALLOW:
1858 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281859 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:181860 else:
1861 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:281862 warning_subjects.add("#includes")
1863
1864 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
1865 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:081866 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:281867 description_with_path = '%s\n %s' % (path, rule_description)
1868 if rule_type == Rule.DISALLOW:
1869 error_descriptions.append(description_with_path)
1870 error_subjects.add("imports")
1871 else:
1872 warning_descriptions.append(description_with_path)
1873 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:181874
Jinsuk Kim5a092672017-10-24 22:42:241875 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:021876 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:081877 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:241878 description_with_path = '%s\n %s' % (path, rule_description)
1879 if rule_type == Rule.DISALLOW:
1880 error_descriptions.append(description_with_path)
1881 error_subjects.add("imports")
1882 else:
1883 warning_descriptions.append(description_with_path)
1884 warning_subjects.add("imports")
1885
[email protected]55f9f382012-07-31 11:02:181886 results = []
1887 if error_descriptions:
1888 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:281889 'You added one or more %s that violate checkdeps rules.'
1890 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:181891 error_descriptions))
1892 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:421893 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:281894 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:181895 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:281896 '%s? See relevant DEPS file(s) for details and contacts.' %
1897 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:181898 warning_descriptions))
1899 return results
1900
1901
[email protected]fbcafe5a2012-08-08 15:31:221902def _CheckFilePermissions(input_api, output_api):
1903 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:151904 if input_api.platform == 'win32':
1905 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:291906 checkperms_tool = input_api.os_path.join(
1907 input_api.PresubmitLocalPath(),
1908 'tools', 'checkperms', 'checkperms.py')
1909 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:471910 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:391911 with input_api.CreateTemporaryFile() as file_list:
1912 for f in input_api.AffectedFiles():
1913 # checkperms.py file/directory arguments must be relative to the
1914 # repository.
1915 file_list.write(f.LocalPath() + '\n')
1916 file_list.close()
1917 args += ['--file-list', file_list.name]
1918 try:
1919 input_api.subprocess.check_output(args)
1920 return []
1921 except input_api.subprocess.CalledProcessError as error:
1922 return [output_api.PresubmitError(
1923 'checkperms.py failed:',
1924 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:221925
1926
robertocn832f5992017-01-04 19:01:301927def _CheckTeamTags(input_api, output_api):
1928 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
1929 checkteamtags_tool = input_api.os_path.join(
1930 input_api.PresubmitLocalPath(),
1931 'tools', 'checkteamtags', 'checkteamtags.py')
1932 args = [input_api.python_executable, checkteamtags_tool,
1933 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:221934 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:301935 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
1936 'OWNERS']
1937 try:
1938 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:051939 warnings = input_api.subprocess.check_output(args + files).splitlines()
1940 if warnings:
1941 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:301942 return []
1943 except input_api.subprocess.CalledProcessError as error:
1944 return [output_api.PresubmitError(
1945 'checkteamtags.py failed:',
1946 long_text=error.output)]
1947
1948
[email protected]c8278b32012-10-30 20:35:491949def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
1950 """Makes sure we don't include ui/aura/window_property.h
1951 in header files.
1952 """
1953 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
1954 errors = []
1955 for f in input_api.AffectedFiles():
1956 if not f.LocalPath().endswith('.h'):
1957 continue
1958 for line_num, line in f.ChangedContents():
1959 if pattern.match(line):
1960 errors.append(' %s:%d' % (f.LocalPath(), line_num))
1961
1962 results = []
1963 if errors:
1964 results.append(output_api.PresubmitError(
1965 'Header files should not include ui/aura/window_property.h', errors))
1966 return results
1967
1968
[email protected]70ca77752012-11-20 03:45:031969def _CheckForVersionControlConflictsInFile(input_api, f):
1970 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
1971 errors = []
1972 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:161973 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:231974 # First-level headers in markdown look a lot like version control
1975 # conflict markers. http://daringfireball.net/projects/markdown/basics
1976 continue
[email protected]70ca77752012-11-20 03:45:031977 if pattern.match(line):
1978 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1979 return errors
1980
1981
1982def _CheckForVersionControlConflicts(input_api, output_api):
1983 """Usually this is not intentional and will cause a compile failure."""
1984 errors = []
1985 for f in input_api.AffectedFiles():
1986 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1987
1988 results = []
1989 if errors:
1990 results.append(output_api.PresubmitError(
1991 'Version control conflict markers found, please resolve.', errors))
1992 return results
1993
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201994
estadee17314a02017-01-12 16:22:161995def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1996 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1997 errors = []
1998 for f in input_api.AffectedFiles():
1999 for line_num, line in f.ChangedContents():
2000 if pattern.search(line):
2001 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2002
2003 results = []
2004 if errors:
2005 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502006 'Found Google support URL addressed by answer number. Please replace '
2007 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162008 return results
2009
[email protected]70ca77752012-11-20 03:45:032010
[email protected]06e6d0ff2012-12-11 01:36:442011def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2012 def FilterFile(affected_file):
2013 """Filter function for use with input_api.AffectedSourceFiles,
2014 below. This filters out everything except non-test files from
2015 top-level directories that generally speaking should not hard-code
2016 service URLs (e.g. src/android_webview/, src/content/ and others).
2017 """
2018 return input_api.FilterSourceFile(
2019 affected_file,
Egor Paskoce145c42018-09-28 19:31:042020 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442021 black_list=(_EXCLUDED_PATHS +
2022 _TEST_CODE_EXCLUDED_PATHS +
2023 input_api.DEFAULT_BLACK_LIST))
2024
reillyi38965732015-11-16 18:27:332025 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2026 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462027 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2028 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442029 problems = [] # items are (filename, line_number, line)
2030 for f in input_api.AffectedSourceFiles(FilterFile):
2031 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462032 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442033 problems.append((f.LocalPath(), line_num, line))
2034
2035 if problems:
[email protected]f7051d52013-04-02 18:31:422036 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442037 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582038 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442039 [' %s:%d: %s' % (
2040 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032041 else:
2042 return []
[email protected]06e6d0ff2012-12-11 01:36:442043
2044
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492045# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272046def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2047 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312048 The native_client_sdk directory is excluded because it has auto-generated PNG
2049 files for documentation.
[email protected]d2530012013-01-25 16:39:272050 """
[email protected]d2530012013-01-25 16:39:272051 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492052 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042053 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312054 file_filter = lambda f: input_api.FilterSourceFile(
2055 f, white_list=white_list, black_list=black_list)
2056 for f in input_api.AffectedFiles(include_deletes=False,
2057 file_filter=file_filter):
2058 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272059
2060 results = []
2061 if errors:
2062 results.append(output_api.PresubmitError(
2063 'The name of PNG files should not have abbreviations. \n'
2064 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2065 'Contact [email protected] if you have questions.', errors))
2066 return results
2067
2068
Daniel Cheng4dcdb6b2017-04-13 08:30:172069def _ExtractAddRulesFromParsedDeps(parsed_deps):
2070 """Extract the rules that add dependencies from a parsed DEPS file.
2071
2072 Args:
2073 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2074 add_rules = set()
2075 add_rules.update([
2076 rule[1:] for rule in parsed_deps.get('include_rules', [])
2077 if rule.startswith('+') or rule.startswith('!')
2078 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502079 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172080 {}).iteritems():
2081 add_rules.update([
2082 rule[1:] for rule in rules
2083 if rule.startswith('+') or rule.startswith('!')
2084 ])
2085 return add_rules
2086
2087
2088def _ParseDeps(contents):
2089 """Simple helper for parsing DEPS files."""
2090 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172091 class _VarImpl:
2092
2093 def __init__(self, local_scope):
2094 self._local_scope = local_scope
2095
2096 def Lookup(self, var_name):
2097 """Implements the Var syntax."""
2098 try:
2099 return self._local_scope['vars'][var_name]
2100 except KeyError:
2101 raise Exception('Var is not defined: %s' % var_name)
2102
2103 local_scope = {}
2104 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172105 'Var': _VarImpl(local_scope).Lookup,
2106 }
2107 exec contents in global_scope, local_scope
2108 return local_scope
2109
2110
2111def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082112 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412113 a set of DEPS entries that we should look up.
2114
2115 For a directory (rather than a specific filename) we fake a path to
2116 a specific filename by adding /DEPS. This is chosen as a file that
2117 will seldom or never be subject to per-file include_rules.
2118 """
[email protected]2b438d62013-11-14 17:54:142119 # We ignore deps entries on auto-generated directories.
2120 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082121
Daniel Cheng4dcdb6b2017-04-13 08:30:172122 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2123 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2124
2125 added_deps = new_deps.difference(old_deps)
2126
[email protected]2b438d62013-11-14 17:54:142127 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172128 for added_dep in added_deps:
2129 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2130 continue
2131 # Assume that a rule that ends in .h is a rule for a specific file.
2132 if added_dep.endswith('.h'):
2133 results.add(added_dep)
2134 else:
2135 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082136 return results
2137
2138
[email protected]e871964c2013-05-13 14:14:552139def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2140 """When a dependency prefixed with + is added to a DEPS file, we
2141 want to make sure that the change is reviewed by an OWNER of the
2142 target file or directory, to avoid layering violations from being
2143 introduced. This check verifies that this happens.
2144 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172145 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242146
2147 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492148 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242149 for f in input_api.AffectedFiles(include_deletes=False,
2150 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552151 filename = input_api.os_path.basename(f.LocalPath())
2152 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172153 virtual_depended_on_files.update(_CalculateAddedDeps(
2154 input_api.os_path,
2155 '\n'.join(f.OldContents()),
2156 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552157
[email protected]e871964c2013-05-13 14:14:552158 if not virtual_depended_on_files:
2159 return []
2160
2161 if input_api.is_committing:
2162 if input_api.tbr:
2163 return [output_api.PresubmitNotifyResult(
2164 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272165 if input_api.dry_run:
2166 return [output_api.PresubmitNotifyResult(
2167 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552168 if not input_api.change.issue:
2169 return [output_api.PresubmitError(
2170 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402171 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552172 output = output_api.PresubmitError
2173 else:
2174 output = output_api.PresubmitNotifyResult
2175
2176 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502177 owner_email, reviewers = (
2178 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2179 input_api,
2180 owners_db.email_regexp,
2181 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552182
2183 owner_email = owner_email or input_api.change.author_email
2184
[email protected]de4f7d22013-05-23 14:27:462185 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512186 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462187 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552188 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2189 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412190
2191 # We strip the /DEPS part that was added by
2192 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2193 # directory.
2194 def StripDeps(path):
2195 start_deps = path.rfind('/DEPS')
2196 if start_deps != -1:
2197 return path[:start_deps]
2198 else:
2199 return path
2200 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552201 for path in missing_files]
2202
2203 if unapproved_dependencies:
2204 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152205 output('You need LGTM from owners of depends-on paths in DEPS that were '
2206 'modified in this CL:\n %s' %
2207 '\n '.join(sorted(unapproved_dependencies)))]
2208 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2209 output_list.append(output(
2210 'Suggested missing target path OWNERS:\n %s' %
2211 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552212 return output_list
2213
2214 return []
2215
2216
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492217# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402218def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492219 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402220 black_list = (_EXCLUDED_PATHS +
2221 _TEST_CODE_EXCLUDED_PATHS +
2222 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042223 (r"^base[\\/]logging\.h$",
2224 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222225 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042226 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2227 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2228 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122229 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182230 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152231 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032232 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152233 r"^chrome[\\/]chrome_cleaner[\\/].*",
2234 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2235 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042236 r"^chromecast[\\/]",
2237 r"^cloud_print[\\/]",
2238 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482239 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042240 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312241 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042242 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462243 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042244 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462245 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042246 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252247 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042248 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2249 r"^courgette[\\/]courgette_tool\.cc$",
2250 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272251 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332252 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042253 r"^ipc[\\/]ipc_logging\.cc$",
2254 r"^native_client_sdk[\\/]",
2255 r"^remoting[\\/]base[\\/]logging\.h$",
2256 r"^remoting[\\/]host[\\/].*",
2257 r"^sandbox[\\/]linux[\\/].*",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332258 r"^storage[\\/]browser[\\/]fileapi[\\/]" +
2259 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042260 r"^tools[\\/]",
2261 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2262 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332263 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402264 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492265 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402266
thomasanderson625d3932017-03-29 07:16:582267 log_info = set([])
2268 printf = set([])
[email protected]85218562013-11-22 07:41:402269
2270 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582271 for _, line in f.ChangedContents():
2272 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2273 log_info.add(f.LocalPath())
2274 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2275 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372276
thomasanderson625d3932017-03-29 07:16:582277 if input_api.re.search(r"\bprintf\(", line):
2278 printf.add(f.LocalPath())
2279 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2280 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402281
2282 if log_info:
2283 return [output_api.PresubmitError(
2284 'These files spam the console log with LOG(INFO):',
2285 items=log_info)]
2286 if printf:
2287 return [output_api.PresubmitError(
2288 'These files spam the console log with printf/fprintf:',
2289 items=printf)]
2290 return []
2291
2292
[email protected]49aa76a2013-12-04 06:59:162293def _CheckForAnonymousVariables(input_api, output_api):
2294 """These types are all expected to hold locks while in scope and
2295 so should never be anonymous (which causes them to be immediately
2296 destroyed)."""
2297 they_who_must_be_named = [
2298 'base::AutoLock',
2299 'base::AutoReset',
2300 'base::AutoUnlock',
2301 'SkAutoAlphaRestore',
2302 'SkAutoBitmapShaderInstall',
2303 'SkAutoBlitterChoose',
2304 'SkAutoBounderCommit',
2305 'SkAutoCallProc',
2306 'SkAutoCanvasRestore',
2307 'SkAutoCommentBlock',
2308 'SkAutoDescriptor',
2309 'SkAutoDisableDirectionCheck',
2310 'SkAutoDisableOvalCheck',
2311 'SkAutoFree',
2312 'SkAutoGlyphCache',
2313 'SkAutoHDC',
2314 'SkAutoLockColors',
2315 'SkAutoLockPixels',
2316 'SkAutoMalloc',
2317 'SkAutoMaskFreeImage',
2318 'SkAutoMutexAcquire',
2319 'SkAutoPathBoundsUpdate',
2320 'SkAutoPDFRelease',
2321 'SkAutoRasterClipValidate',
2322 'SkAutoRef',
2323 'SkAutoTime',
2324 'SkAutoTrace',
2325 'SkAutoUnref',
2326 ]
2327 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2328 # bad: base::AutoLock(lock.get());
2329 # not bad: base::AutoLock lock(lock.get());
2330 bad_pattern = input_api.re.compile(anonymous)
2331 # good: new base::AutoLock(lock.get())
2332 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2333 errors = []
2334
2335 for f in input_api.AffectedFiles():
2336 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2337 continue
2338 for linenum, line in f.ChangedContents():
2339 if bad_pattern.search(line) and not good_pattern.search(line):
2340 errors.append('%s:%d' % (f.LocalPath(), linenum))
2341
2342 if errors:
2343 return [output_api.PresubmitError(
2344 'These lines create anonymous variables that need to be named:',
2345 items=errors)]
2346 return []
2347
2348
Peter Kasting4844e46e2018-02-23 07:27:102349def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532350 # Returns whether |template_str| is of the form <T, U...> for some types T
2351 # and U. Assumes that |template_str| is already in the form <...>.
2352 def HasMoreThanOneArg(template_str):
2353 # Level of <...> nesting.
2354 nesting = 0
2355 for c in template_str:
2356 if c == '<':
2357 nesting += 1
2358 elif c == '>':
2359 nesting -= 1
2360 elif c == ',' and nesting == 1:
2361 return True
2362 return False
2363
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492364 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102365 sources = lambda affected_file: input_api.FilterSourceFile(
2366 affected_file,
2367 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2368 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492369 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552370
2371 # Pattern to capture a single "<...>" block of template arguments. It can
2372 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2373 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2374 # latter would likely require counting that < and > match, which is not
2375 # expressible in regular languages. Should the need arise, one can introduce
2376 # limited counting (matching up to a total number of nesting depth), which
2377 # should cover all practical cases for already a low nesting limit.
2378 template_arg_pattern = (
2379 r'<[^>]*' # Opening block of <.
2380 r'>([^<]*>)?') # Closing block of >.
2381 # Prefix expressing that whatever follows is not already inside a <...>
2382 # block.
2383 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102384 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552385 not_inside_template_arg_pattern
2386 + r'\bstd::unique_ptr'
2387 + template_arg_pattern
2388 + r'\(\)')
2389
2390 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2391 template_arg_no_array_pattern = (
2392 r'<[^>]*[^]]' # Opening block of <.
2393 r'>([^(<]*[^]]>)?') # Closing block of >.
2394 # Prefix saying that what follows is the start of an expression.
2395 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2396 # Suffix saying that what follows are call parentheses with a non-empty list
2397 # of arguments.
2398 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532399 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552400 return_construct_pattern = input_api.re.compile(
2401 start_of_expr_pattern
2402 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532403 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552404 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532405 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552406 + nonempty_arg_list_pattern)
2407
Vaclav Brozek851d9602018-04-04 16:13:052408 problems_constructor = []
2409 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102410 for f in input_api.AffectedSourceFiles(sources):
2411 for line_number, line in f.ChangedContents():
2412 # Disallow:
2413 # return std::unique_ptr<T>(foo);
2414 # bar = std::unique_ptr<T>(foo);
2415 # But allow:
2416 # return std::unique_ptr<T[]>(foo);
2417 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532418 # And also allow cases when the second template argument is present. Those
2419 # cases cannot be handled by std::make_unique:
2420 # return std::unique_ptr<T, U>(foo);
2421 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052422 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532423 return_construct_result = return_construct_pattern.search(line)
2424 if return_construct_result and not HasMoreThanOneArg(
2425 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052426 problems_constructor.append(
2427 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102428 # Disallow:
2429 # std::unique_ptr<T>()
2430 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052431 problems_nullptr.append(
2432 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2433
2434 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162435 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052436 errors.append(output_api.PresubmitError(
2437 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162438 problems_nullptr))
2439 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052440 errors.append(output_api.PresubmitError(
2441 'The following files use explicit std::unique_ptr constructor.'
2442 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162443 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102444 return errors
2445
2446
[email protected]999261d2014-03-03 20:08:082447def _CheckUserActionUpdate(input_api, output_api):
2448 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522449 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082450 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522451 # If actions.xml is already included in the changelist, the PRESUBMIT
2452 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082453 return []
2454
[email protected]999261d2014-03-03 20:08:082455 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2456 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522457 current_actions = None
[email protected]999261d2014-03-03 20:08:082458 for f in input_api.AffectedFiles(file_filter=file_filter):
2459 for line_num, line in f.ChangedContents():
2460 match = input_api.re.search(action_re, line)
2461 if match:
[email protected]2f92dec2014-03-07 19:21:522462 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2463 # loaded only once.
2464 if not current_actions:
2465 with open('tools/metrics/actions/actions.xml') as actions_f:
2466 current_actions = actions_f.read()
2467 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082468 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522469 action = 'name="{0}"'.format(action_name)
2470 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082471 return [output_api.PresubmitPromptWarning(
2472 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522473 'tools/metrics/actions/actions.xml. Please run '
2474 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082475 % (f.LocalPath(), line_num, action_name))]
2476 return []
2477
2478
Daniel Cheng13ca61a882017-08-25 15:11:252479def _ImportJSONCommentEater(input_api):
2480 import sys
2481 sys.path = sys.path + [input_api.os_path.join(
2482 input_api.PresubmitLocalPath(),
2483 'tools', 'json_comment_eater')]
2484 import json_comment_eater
2485 return json_comment_eater
2486
2487
[email protected]99171a92014-06-03 08:44:472488def _GetJSONParseError(input_api, filename, eat_comments=True):
2489 try:
2490 contents = input_api.ReadFile(filename)
2491 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252492 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132493 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472494
2495 input_api.json.loads(contents)
2496 except ValueError as e:
2497 return e
2498 return None
2499
2500
2501def _GetIDLParseError(input_api, filename):
2502 try:
2503 contents = input_api.ReadFile(filename)
2504 idl_schema = input_api.os_path.join(
2505 input_api.PresubmitLocalPath(),
2506 'tools', 'json_schema_compiler', 'idl_schema.py')
2507 process = input_api.subprocess.Popen(
2508 [input_api.python_executable, idl_schema],
2509 stdin=input_api.subprocess.PIPE,
2510 stdout=input_api.subprocess.PIPE,
2511 stderr=input_api.subprocess.PIPE,
2512 universal_newlines=True)
2513 (_, error) = process.communicate(input=contents)
2514 return error or None
2515 except ValueError as e:
2516 return e
2517
2518
2519def _CheckParseErrors(input_api, output_api):
2520 """Check that IDL and JSON files do not contain syntax errors."""
2521 actions = {
2522 '.idl': _GetIDLParseError,
2523 '.json': _GetJSONParseError,
2524 }
[email protected]99171a92014-06-03 08:44:472525 # Most JSON files are preprocessed and support comments, but these do not.
2526 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042527 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472528 ]
2529 # Only run IDL checker on files in these directories.
2530 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042531 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2532 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472533 ]
2534
2535 def get_action(affected_file):
2536 filename = affected_file.LocalPath()
2537 return actions.get(input_api.os_path.splitext(filename)[1])
2538
[email protected]99171a92014-06-03 08:44:472539 def FilterFile(affected_file):
2540 action = get_action(affected_file)
2541 if not action:
2542 return False
2543 path = affected_file.LocalPath()
2544
Sean Kau46e29bc2017-08-28 16:31:162545 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472546 return False
2547
2548 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162549 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472550 return False
2551 return True
2552
2553 results = []
2554 for affected_file in input_api.AffectedFiles(
2555 file_filter=FilterFile, include_deletes=False):
2556 action = get_action(affected_file)
2557 kwargs = {}
2558 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162559 _MatchesFile(input_api, json_no_comments_patterns,
2560 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472561 kwargs['eat_comments'] = False
2562 parse_error = action(input_api,
2563 affected_file.AbsoluteLocalPath(),
2564 **kwargs)
2565 if parse_error:
2566 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2567 (affected_file.LocalPath(), parse_error)))
2568 return results
2569
2570
[email protected]760deea2013-12-10 19:33:492571def _CheckJavaStyle(input_api, output_api):
2572 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472573 import sys
[email protected]760deea2013-12-10 19:33:492574 original_sys_path = sys.path
2575 try:
2576 sys.path = sys.path + [input_api.os_path.join(
2577 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2578 import checkstyle
2579 finally:
2580 # Restore sys.path to what it was before.
2581 sys.path = original_sys_path
2582
2583 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092584 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512585 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492586
2587
Nate Fischerdfd9812e2019-07-18 22:03:002588def _CheckPythonDevilInit(input_api, output_api):
2589 """Checks to make sure devil is initialized correctly in python scripts."""
2590 script_common_initialize_pattern = input_api.re.compile(
2591 r'script_common\.InitializeEnvironment\(')
2592 devil_env_config_initialize = input_api.re.compile(
2593 r'devil_env\.config\.Initialize\(')
2594
2595 errors = []
2596
2597 sources = lambda affected_file: input_api.FilterSourceFile(
2598 affected_file,
2599 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2600 (r'^build[\\/]android[\\/]devil_chromium\.py',
2601 r'^third_party[\\/].*',)),
2602 white_list=[r'.*\.py$'])
2603
2604 for f in input_api.AffectedSourceFiles(sources):
2605 for line_num, line in f.ChangedContents():
2606 if (script_common_initialize_pattern.search(line) or
2607 devil_env_config_initialize.search(line)):
2608 errors.append("%s:%d" % (f.LocalPath(), line_num))
2609
2610 results = []
2611
2612 if errors:
2613 results.append(output_api.PresubmitError(
2614 'Devil initialization should always be done using '
2615 'devil_chromium.Initialize() in the chromium project, to use better '
2616 'defaults for dependencies (ex. up-to-date version of adb).',
2617 errors))
2618
2619 return results
2620
2621
Sean Kau46e29bc2017-08-28 16:31:162622def _MatchesFile(input_api, patterns, path):
2623 for pattern in patterns:
2624 if input_api.re.search(pattern, path):
2625 return True
2626 return False
2627
2628
Daniel Cheng7052cdf2017-11-21 19:23:292629def _GetOwnersFilesToCheckForIpcOwners(input_api):
2630 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172631
Daniel Cheng7052cdf2017-11-21 19:23:292632 Returns:
2633 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2634 contain to cover IPC-related files with noparent reviewer rules.
2635 """
2636 # Whether or not a file affects IPC is (mostly) determined by a simple list
2637 # of filename patterns.
dchenge07de812016-06-20 19:27:172638 file_patterns = [
palmerb19a0932017-01-24 04:00:312639 # Legacy IPC:
dchenge07de812016-06-20 19:27:172640 '*_messages.cc',
2641 '*_messages*.h',
2642 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312643 # Mojo IPC:
dchenge07de812016-06-20 19:27:172644 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472645 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172646 '*_struct_traits*.*',
2647 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312648 '*.typemap',
2649 # Android native IPC:
2650 '*.aidl',
2651 # Blink uses a different file naming convention:
2652 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472653 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172654 '*StructTraits*.*',
2655 '*TypeConverter*.*',
2656 ]
2657
scottmg7a6ed5ba2016-11-04 18:22:042658 # These third_party directories do not contain IPCs, but contain files
2659 # matching the above patterns, which trigger false positives.
2660 exclude_paths = [
2661 'third_party/crashpad/*',
Andres Medinae684cf42018-08-27 18:48:232662 'third_party/protobuf/benchmarks/python/*',
Daniel Chengebe635e2018-07-13 12:36:062663 'third_party/third_party/blink/renderer/platform/bindings/*',
Nico Weberee3dc9b2017-08-31 17:09:292664 'third_party/win_build_output/*',
scottmg7a6ed5ba2016-11-04 18:22:042665 ]
2666
dchenge07de812016-06-20 19:27:172667 # Dictionary mapping an OWNERS file path to Patterns.
2668 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2669 # rules ) to a PatternEntry.
2670 # PatternEntry is a dictionary with two keys:
2671 # - 'files': the files that are matched by this pattern
2672 # - 'rules': the per-file rules needed for this pattern
2673 # For example, if we expect OWNERS file to contain rules for *.mojom and
2674 # *_struct_traits*.*, Patterns might look like this:
2675 # {
2676 # '*.mojom': {
2677 # 'files': ...,
2678 # 'rules': [
2679 # 'per-file *.mojom=set noparent',
2680 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2681 # ],
2682 # },
2683 # '*_struct_traits*.*': {
2684 # 'files': ...,
2685 # 'rules': [
2686 # 'per-file *_struct_traits*.*=set noparent',
2687 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2688 # ],
2689 # },
2690 # }
2691 to_check = {}
2692
Daniel Cheng13ca61a882017-08-25 15:11:252693 def AddPatternToCheck(input_file, pattern):
2694 owners_file = input_api.os_path.join(
2695 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2696 if owners_file not in to_check:
2697 to_check[owners_file] = {}
2698 if pattern not in to_check[owners_file]:
2699 to_check[owners_file][pattern] = {
2700 'files': [],
2701 'rules': [
2702 'per-file %s=set noparent' % pattern,
2703 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2704 ]
2705 }
Vaclav Brozekd5de76a2018-03-17 07:57:502706 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252707
dchenge07de812016-06-20 19:27:172708 # Iterate through the affected files to see what we actually need to check
2709 # for. We should only nag patch authors about per-file rules if a file in that
2710 # directory would match that pattern. If a directory only contains *.mojom
2711 # files and no *_messages*.h files, we should only nag about rules for
2712 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252713 for f in input_api.AffectedFiles(include_deletes=False):
2714 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362715 # affected files for .json, .cc, and .h files which look like they contain
2716 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162717 if (f.LocalPath().endswith('.json') and
2718 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2719 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252720 json_comment_eater = _ImportJSONCommentEater(input_api)
2721 mostly_json_lines = '\n'.join(f.NewContents())
2722 # Comments aren't allowed in strict JSON, so filter them out.
2723 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432724 try:
2725 json_content = input_api.json.loads(json_lines)
2726 except:
2727 # There's another PRESUBMIT check that already verifies that JSON files
2728 # are not invalid, so no need to emit another warning here.
2729 continue
Daniel Cheng13ca61a882017-08-25 15:11:252730 if 'interface_provider_specs' in json_content:
2731 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362732 else:
2733 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2734 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2735 if (manifest_pattern.search(f.LocalPath()) and not
2736 test_manifest_pattern.search(f.LocalPath())):
2737 # We expect all actual service manifest files to contain at least one
2738 # qualified reference to service_manager::Manifest.
2739 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2740 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172741 for pattern in file_patterns:
2742 if input_api.fnmatch.fnmatch(
2743 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042744 skip = False
2745 for exclude in exclude_paths:
2746 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2747 skip = True
2748 break
2749 if skip:
2750 continue
Daniel Cheng13ca61a882017-08-25 15:11:252751 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172752 break
2753
Daniel Cheng7052cdf2017-11-21 19:23:292754 return to_check
2755
2756
2757def _CheckIpcOwners(input_api, output_api):
2758 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2759 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2760
2761 if to_check:
2762 # If there are any OWNERS files to check, there are IPC-related changes in
2763 # this CL. Auto-CC the review list.
2764 output_api.AppendCC('[email protected]')
2765
2766 # Go through the OWNERS files to check, filtering out rules that are already
2767 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172768 for owners_file, patterns in to_check.iteritems():
2769 try:
2770 with file(owners_file) as f:
2771 lines = set(f.read().splitlines())
2772 for entry in patterns.itervalues():
2773 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2774 ]
2775 except IOError:
2776 # No OWNERS file, so all the rules are definitely missing.
2777 continue
2778
2779 # All the remaining lines weren't found in OWNERS files, so emit an error.
2780 errors = []
2781 for owners_file, patterns in to_check.iteritems():
2782 missing_lines = []
2783 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502784 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172785 missing_lines.extend(entry['rules'])
2786 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2787 if missing_lines:
2788 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:052789 'Because of the presence of files:\n%s\n\n'
2790 '%s needs the following %d lines added:\n\n%s' %
2791 ('\n'.join(files), owners_file, len(missing_lines),
2792 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:172793
2794 results = []
2795 if errors:
vabrf5ce3bf92016-07-11 14:52:412796 if input_api.is_committing:
2797 output = output_api.PresubmitError
2798 else:
2799 output = output_api.PresubmitPromptWarning
2800 results.append(output(
Daniel Cheng52111692017-06-14 08:00:592801 'Found OWNERS files that need to be updated for IPC security ' +
2802 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:172803 long_text='\n\n'.join(errors)))
2804
2805 return results
2806
2807
jbriance9e12f162016-11-25 07:57:502808def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:312809 """Checks that added or removed lines in non third party affected
2810 header files do not lead to new useless class or struct forward
2811 declaration.
jbriance9e12f162016-11-25 07:57:502812 """
2813 results = []
2814 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
2815 input_api.re.MULTILINE)
2816 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
2817 input_api.re.MULTILINE)
2818 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:312819 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:192820 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:492821 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:312822 continue
2823
jbriance9e12f162016-11-25 07:57:502824 if not f.LocalPath().endswith('.h'):
2825 continue
2826
2827 contents = input_api.ReadFile(f)
2828 fwd_decls = input_api.re.findall(class_pattern, contents)
2829 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
2830
2831 useless_fwd_decls = []
2832 for decl in fwd_decls:
2833 count = sum(1 for _ in input_api.re.finditer(
2834 r'\b%s\b' % input_api.re.escape(decl), contents))
2835 if count == 1:
2836 useless_fwd_decls.append(decl)
2837
2838 if not useless_fwd_decls:
2839 continue
2840
2841 for line in f.GenerateScmDiff().splitlines():
2842 if (line.startswith('-') and not line.startswith('--') or
2843 line.startswith('+') and not line.startswith('++')):
2844 for decl in useless_fwd_decls:
2845 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
2846 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:242847 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:502848 (f.LocalPath(), decl)))
2849 useless_fwd_decls.remove(decl)
2850
2851 return results
2852
Jinsong Fan91ebbbd2019-04-16 14:57:172853def _CheckAndroidDebuggableBuild(input_api, output_api):
2854 """Checks that code uses BuildInfo.isDebugAndroid() instead of
2855 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
2856 this is a debuggable build of Android.
2857 """
2858 build_type_check_pattern = input_api.re.compile(
2859 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
2860
2861 errors = []
2862
2863 sources = lambda affected_file: input_api.FilterSourceFile(
2864 affected_file,
2865 black_list=(_EXCLUDED_PATHS +
2866 _TEST_CODE_EXCLUDED_PATHS +
2867 input_api.DEFAULT_BLACK_LIST +
2868 (r"^android_webview[\\/]support_library[\\/]"
2869 "boundary_interfaces[\\/]",
2870 r"^chrome[\\/]android[\\/]webapk[\\/].*",
2871 r'^third_party[\\/].*',
2872 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
2873 r"webview[\\/]chromium[\\/]License.*",)),
2874 white_list=[r'.*\.java$'])
2875
2876 for f in input_api.AffectedSourceFiles(sources):
2877 for line_num, line in f.ChangedContents():
2878 if build_type_check_pattern.search(line):
2879 errors.append("%s:%d" % (f.LocalPath(), line_num))
2880
2881 results = []
2882
2883 if errors:
2884 results.append(output_api.PresubmitPromptWarning(
2885 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
2886 ' Please use BuildInfo.isDebugAndroid() instead.',
2887 errors))
2888
2889 return results
jbriance9e12f162016-11-25 07:57:502890
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492891# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:292892def _CheckAndroidToastUsage(input_api, output_api):
2893 """Checks that code uses org.chromium.ui.widget.Toast instead of
2894 android.widget.Toast (Chromium Toast doesn't force hardware
2895 acceleration on low-end devices, saving memory).
2896 """
2897 toast_import_pattern = input_api.re.compile(
2898 r'^import android\.widget\.Toast;$')
2899
2900 errors = []
2901
2902 sources = lambda affected_file: input_api.FilterSourceFile(
2903 affected_file,
2904 black_list=(_EXCLUDED_PATHS +
2905 _TEST_CODE_EXCLUDED_PATHS +
2906 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042907 (r'^chromecast[\\/].*',
2908 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492909 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:292910
2911 for f in input_api.AffectedSourceFiles(sources):
2912 for line_num, line in f.ChangedContents():
2913 if toast_import_pattern.search(line):
2914 errors.append("%s:%d" % (f.LocalPath(), line_num))
2915
2916 results = []
2917
2918 if errors:
2919 results.append(output_api.PresubmitError(
2920 'android.widget.Toast usage is detected. Android toasts use hardware'
2921 ' acceleration, and can be\ncostly on low-end devices. Please use'
2922 ' org.chromium.ui.widget.Toast instead.\n'
2923 'Contact [email protected] if you have any questions.',
2924 errors))
2925
2926 return results
2927
2928
dgnaa68d5e2015-06-10 10:08:222929def _CheckAndroidCrLogUsage(input_api, output_api):
2930 """Checks that new logs using org.chromium.base.Log:
2931 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:512932 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:222933 """
pkotwicza1dd0b002016-05-16 14:41:042934
torne89540622017-03-24 19:41:302935 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:042936 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:302937 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:042938 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:302939 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:042940 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
2941 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:092942 # The customtabs_benchmark is a small app that does not depend on Chromium
2943 # java pieces.
Egor Paskoce145c42018-09-28 19:31:042944 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:042945 ]
2946
dgnaa68d5e2015-06-10 10:08:222947 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:122948 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
2949 class_in_base_pattern = input_api.re.compile(
2950 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
2951 has_some_log_import_pattern = input_api.re.compile(
2952 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222953 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:122954 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:222955 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:512956 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:222957 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:222958
Vincent Scheib16d7b272015-09-15 18:09:072959 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:222960 'or contact [email protected] for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492961 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:042962 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:122963
dgnaa68d5e2015-06-10 10:08:222964 tag_decl_errors = []
2965 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:122966 tag_errors = []
dgn38736db2015-09-18 19:20:512967 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:122968 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:222969
2970 for f in input_api.AffectedSourceFiles(sources):
2971 file_content = input_api.ReadFile(f)
2972 has_modified_logs = False
2973
2974 # Per line checks
dgn87d9fb62015-06-12 09:15:122975 if (cr_log_import_pattern.search(file_content) or
2976 (class_in_base_pattern.search(file_content) and
2977 not has_some_log_import_pattern.search(file_content))):
2978 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:222979 for line_num, line in f.ChangedContents():
2980
2981 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:122982 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:222983 if match:
2984 has_modified_logs = True
2985
2986 # Make sure it uses "TAG"
2987 if not match.group('tag') == 'TAG':
2988 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:122989 else:
2990 # Report non cr Log function calls in changed lines
2991 for line_num, line in f.ChangedContents():
2992 if log_call_pattern.search(line):
2993 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:222994
2995 # Per file checks
2996 if has_modified_logs:
2997 # Make sure the tag is using the "cr" prefix and is not too long
2998 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:512999 tag_name = match.group('name') if match else None
3000 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223001 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513002 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223003 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513004 elif '.' in tag_name:
3005 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223006
3007 results = []
3008 if tag_decl_errors:
3009 results.append(output_api.PresubmitPromptWarning(
3010 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513011 '"private static final String TAG = "<package tag>".\n'
3012 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223013 tag_decl_errors))
3014
3015 if tag_length_errors:
3016 results.append(output_api.PresubmitError(
3017 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513018 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223019 tag_length_errors))
3020
3021 if tag_errors:
3022 results.append(output_api.PresubmitPromptWarning(
3023 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3024 tag_errors))
3025
dgn87d9fb62015-06-12 09:15:123026 if util_log_errors:
dgn4401aa52015-04-29 16:26:173027 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123028 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3029 util_log_errors))
3030
dgn38736db2015-09-18 19:20:513031 if tag_with_dot_errors:
3032 results.append(output_api.PresubmitPromptWarning(
3033 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3034 tag_with_dot_errors))
3035
dgn4401aa52015-04-29 16:26:173036 return results
3037
3038
Yoland Yanb92fa522017-08-28 17:37:063039def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3040 """Checks that junit.framework.* is no longer used."""
3041 deprecated_junit_framework_pattern = input_api.re.compile(
3042 r'^import junit\.framework\..*;',
3043 input_api.re.MULTILINE)
3044 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493045 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063046 errors = []
3047 for f in input_api.AffectedFiles(sources):
3048 for line_num, line in f.ChangedContents():
3049 if deprecated_junit_framework_pattern.search(line):
3050 errors.append("%s:%d" % (f.LocalPath(), line_num))
3051
3052 results = []
3053 if errors:
3054 results.append(output_api.PresubmitError(
3055 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3056 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3057 ' if you have any question.', errors))
3058 return results
3059
3060
3061def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3062 """Checks that if new Java test classes have inheritance.
3063 Either the new test class is JUnit3 test or it is a JUnit4 test class
3064 with a base class, either case is undesirable.
3065 """
3066 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3067
3068 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493069 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063070 errors = []
3071 for f in input_api.AffectedFiles(sources):
3072 if not f.OldContents():
3073 class_declaration_start_flag = False
3074 for line_num, line in f.ChangedContents():
3075 if class_declaration_pattern.search(line):
3076 class_declaration_start_flag = True
3077 if class_declaration_start_flag and ' extends ' in line:
3078 errors.append('%s:%d' % (f.LocalPath(), line_num))
3079 if '{' in line:
3080 class_declaration_start_flag = False
3081
3082 results = []
3083 if errors:
3084 results.append(output_api.PresubmitPromptWarning(
3085 'The newly created files include Test classes that inherits from base'
3086 ' class. Please do not use inheritance in JUnit4 tests or add new'
3087 ' JUnit3 tests. Contact [email protected] if you have any'
3088 ' questions.', errors))
3089 return results
3090
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203091
yolandyan45001472016-12-21 21:12:423092def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3093 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3094 deprecated_annotation_import_pattern = input_api.re.compile(
3095 r'^import android\.test\.suitebuilder\.annotation\..*;',
3096 input_api.re.MULTILINE)
3097 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493098 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423099 errors = []
3100 for f in input_api.AffectedFiles(sources):
3101 for line_num, line in f.ChangedContents():
3102 if deprecated_annotation_import_pattern.search(line):
3103 errors.append("%s:%d" % (f.LocalPath(), line_num))
3104
3105 results = []
3106 if errors:
3107 results.append(output_api.PresubmitError(
3108 'Annotations in android.test.suitebuilder.annotation have been'
3109 ' deprecated since API level 24. Please use android.support.test.filters'
3110 ' from //third_party/android_support_test_runner:runner_java instead.'
3111 ' Contact [email protected] if you have any questions.', errors))
3112 return results
3113
3114
agrieve7b6479d82015-10-07 14:24:223115def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3116 """Checks if MDPI assets are placed in a correct directory."""
3117 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3118 ('/res/drawable/' in f.LocalPath() or
3119 '/res/drawable-ldrtl/' in f.LocalPath()))
3120 errors = []
3121 for f in input_api.AffectedFiles(include_deletes=False,
3122 file_filter=file_filter):
3123 errors.append(' %s' % f.LocalPath())
3124
3125 results = []
3126 if errors:
3127 results.append(output_api.PresubmitError(
3128 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3129 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3130 '/res/drawable-ldrtl/.\n'
3131 'Contact [email protected] if you have questions.', errors))
3132 return results
3133
3134
Nate Fischer535972b2017-09-16 01:06:183135def _CheckAndroidWebkitImports(input_api, output_api):
3136 """Checks that code uses org.chromium.base.Callback instead of
3137 android.widget.ValueCallback except in the WebView glue layer.
3138 """
3139 valuecallback_import_pattern = input_api.re.compile(
3140 r'^import android\.webkit\.ValueCallback;$')
3141
3142 errors = []
3143
3144 sources = lambda affected_file: input_api.FilterSourceFile(
3145 affected_file,
3146 black_list=(_EXCLUDED_PATHS +
3147 _TEST_CODE_EXCLUDED_PATHS +
3148 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043149 (r'^android_webview[\\/]glue[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493150 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183151
3152 for f in input_api.AffectedSourceFiles(sources):
3153 for line_num, line in f.ChangedContents():
3154 if valuecallback_import_pattern.search(line):
3155 errors.append("%s:%d" % (f.LocalPath(), line_num))
3156
3157 results = []
3158
3159 if errors:
3160 results.append(output_api.PresubmitError(
3161 'android.webkit.ValueCallback usage is detected outside of the glue'
3162 ' layer. To stay compatible with the support library, android.webkit.*'
3163 ' classes should only be used inside the glue layer and'
3164 ' org.chromium.base.Callback should be used instead.',
3165 errors))
3166
3167 return results
3168
3169
Becky Zhou7c69b50992018-12-10 19:37:573170def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3171 """Checks Android XML styles """
3172 import sys
3173 original_sys_path = sys.path
3174 try:
3175 sys.path = sys.path + [input_api.os_path.join(
3176 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3177 import checkxmlstyle
3178 finally:
3179 # Restore sys.path to what it was before.
3180 sys.path = original_sys_path
3181
3182 if is_check_on_upload:
3183 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3184 else:
3185 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3186
3187
agrievef32bcc72016-04-04 14:57:403188class PydepsChecker(object):
3189 def __init__(self, input_api, pydeps_files):
3190 self._file_cache = {}
3191 self._input_api = input_api
3192 self._pydeps_files = pydeps_files
3193
3194 def _LoadFile(self, path):
3195 """Returns the list of paths within a .pydeps file relative to //."""
3196 if path not in self._file_cache:
3197 with open(path) as f:
3198 self._file_cache[path] = f.read()
3199 return self._file_cache[path]
3200
3201 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3202 """Returns an interable of paths within the .pydep, relativized to //."""
3203 os_path = self._input_api.os_path
3204 pydeps_dir = os_path.dirname(pydeps_path)
3205 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3206 if not l.startswith('*'))
3207 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3208
3209 def _CreateFilesToPydepsMap(self):
3210 """Returns a map of local_path -> list_of_pydeps."""
3211 ret = {}
3212 for pydep_local_path in self._pydeps_files:
3213 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3214 ret.setdefault(path, []).append(pydep_local_path)
3215 return ret
3216
3217 def ComputeAffectedPydeps(self):
3218 """Returns an iterable of .pydeps files that might need regenerating."""
3219 affected_pydeps = set()
3220 file_to_pydeps_map = None
3221 for f in self._input_api.AffectedFiles(include_deletes=True):
3222 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463223 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3224 # subrepositories. We can't figure out which files change, so re-check
3225 # all files.
3226 # Changes to print_python_deps.py affect all .pydeps.
3227 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403228 return self._pydeps_files
3229 elif local_path.endswith('.pydeps'):
3230 if local_path in self._pydeps_files:
3231 affected_pydeps.add(local_path)
3232 elif local_path.endswith('.py'):
3233 if file_to_pydeps_map is None:
3234 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3235 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3236 return affected_pydeps
3237
3238 def DetermineIfStale(self, pydeps_path):
3239 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413240 import difflib
John Budorick47ca3fe2018-02-10 00:53:103241 import os
3242
agrievef32bcc72016-04-04 14:57:403243 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3244 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103245 env = dict(os.environ)
3246 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403247 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103248 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413249 old_contents = old_pydeps_data[2:]
3250 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403251 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413252 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403253
3254
Tibor Goldschwendt360793f72019-06-25 18:23:493255def _ParseGclientArgs():
3256 args = {}
3257 with open('build/config/gclient_args.gni', 'r') as f:
3258 for line in f:
3259 line = line.strip()
3260 if not line or line.startswith('#'):
3261 continue
3262 attribute, value = line.split('=')
3263 args[attribute.strip()] = value.strip()
3264 return args
3265
3266
agrievef32bcc72016-04-04 14:57:403267def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3268 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403269 # This check is for Python dependency lists (.pydeps files), and involves
3270 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3271 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283272 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003273 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493274 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403275 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3276 results = []
3277 # First, check for new / deleted .pydeps.
3278 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033279 # Check whether we are running the presubmit check for a file in src.
3280 # f.LocalPath is relative to repo (src, or internal repo).
3281 # os_path.exists is relative to src repo.
3282 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3283 # to src and we can conclude that the pydeps is in src.
3284 if input_api.os_path.exists(f.LocalPath()):
3285 if f.LocalPath().endswith('.pydeps'):
3286 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3287 results.append(output_api.PresubmitError(
3288 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3289 'remove %s' % f.LocalPath()))
3290 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3291 results.append(output_api.PresubmitError(
3292 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3293 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403294
3295 if results:
3296 return results
3297
3298 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3299
3300 for pydep_path in checker.ComputeAffectedPydeps():
3301 try:
phajdan.jr0d9878552016-11-04 10:49:413302 result = checker.DetermineIfStale(pydep_path)
3303 if result:
3304 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403305 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413306 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3307 'To regenerate, run:\n\n %s' %
3308 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403309 except input_api.subprocess.CalledProcessError as error:
3310 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3311 long_text=error.output)]
3312
3313 return results
3314
3315
glidere61efad2015-02-18 17:39:433316def _CheckSingletonInHeaders(input_api, output_api):
3317 """Checks to make sure no header files have |Singleton<|."""
3318 def FileFilter(affected_file):
3319 # It's ok for base/memory/singleton.h to have |Singleton<|.
3320 black_list = (_EXCLUDED_PATHS +
3321 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043322 (r"^base[\\/]memory[\\/]singleton\.h$",
3323 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473324 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433325 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3326
sergeyu34d21222015-09-16 00:11:443327 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433328 files = []
3329 for f in input_api.AffectedSourceFiles(FileFilter):
3330 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3331 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3332 contents = input_api.ReadFile(f)
3333 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243334 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433335 pattern.search(line)):
3336 files.append(f)
3337 break
3338
3339 if files:
yolandyandaabc6d2016-04-18 18:29:393340 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443341 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433342 'Please move them to an appropriate source file so that the ' +
3343 'template gets instantiated in a single compilation unit.',
3344 files) ]
3345 return []
3346
3347
[email protected]fd20b902014-05-09 02:14:533348_DEPRECATED_CSS = [
3349 # Values
3350 ( "-webkit-box", "flex" ),
3351 ( "-webkit-inline-box", "inline-flex" ),
3352 ( "-webkit-flex", "flex" ),
3353 ( "-webkit-inline-flex", "inline-flex" ),
3354 ( "-webkit-min-content", "min-content" ),
3355 ( "-webkit-max-content", "max-content" ),
3356
3357 # Properties
3358 ( "-webkit-background-clip", "background-clip" ),
3359 ( "-webkit-background-origin", "background-origin" ),
3360 ( "-webkit-background-size", "background-size" ),
3361 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443362 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533363
3364 # Functions
3365 ( "-webkit-gradient", "gradient" ),
3366 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3367 ( "-webkit-linear-gradient", "linear-gradient" ),
3368 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3369 ( "-webkit-radial-gradient", "radial-gradient" ),
3370 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3371]
3372
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203373
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493374# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243375def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533376 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253377 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343378 documentation and iOS CSS for dom distiller
3379 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253380 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533381 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493382 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253383 black_list = (_EXCLUDED_PATHS +
3384 _TEST_CODE_EXCLUDED_PATHS +
3385 input_api.DEFAULT_BLACK_LIST +
3386 (r"^chrome/common/extensions/docs",
3387 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343388 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443389 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253390 r"^native_client_sdk"))
3391 file_filter = lambda f: input_api.FilterSourceFile(
3392 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533393 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3394 for line_num, line in fpath.ChangedContents():
3395 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023396 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533397 results.append(output_api.PresubmitError(
3398 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3399 (fpath.LocalPath(), line_num, deprecated_value, value)))
3400 return results
3401
mohan.reddyf21db962014-10-16 12:26:473402
rlanday6802cf632017-05-30 17:48:363403def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363404 bad_files = {}
3405 for f in input_api.AffectedFiles(include_deletes=False):
3406 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493407 not f.LocalPath().startswith('third_party/blink') and
3408 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363409 continue
3410
Daniel Bratell65b033262019-04-23 08:17:063411 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363412 continue
3413
Vaclav Brozekd5de76a2018-03-17 07:57:503414 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363415 if "#include" in line and "../" in line]
3416 if not relative_includes:
3417 continue
3418 bad_files[f.LocalPath()] = relative_includes
3419
3420 if not bad_files:
3421 return []
3422
3423 error_descriptions = []
3424 for file_path, bad_lines in bad_files.iteritems():
3425 error_description = file_path
3426 for line in bad_lines:
3427 error_description += '\n ' + line
3428 error_descriptions.append(error_description)
3429
3430 results = []
3431 results.append(output_api.PresubmitError(
3432 'You added one or more relative #include paths (including "../").\n'
3433 'These shouldn\'t be used because they can be used to include headers\n'
3434 'from code that\'s not correctly specified as a dependency in the\n'
3435 'relevant BUILD.gn file(s).',
3436 error_descriptions))
3437
3438 return results
3439
Takeshi Yoshinoe387aa32017-08-02 13:16:133440
Daniel Bratell65b033262019-04-23 08:17:063441def _CheckForCcIncludes(input_api, output_api):
3442 """Check that nobody tries to include a cc file. It's a relatively
3443 common error which results in duplicate symbols in object
3444 files. This may not always break the build until someone later gets
3445 very confusing linking errors."""
3446 results = []
3447 for f in input_api.AffectedFiles(include_deletes=False):
3448 # We let third_party code do whatever it wants
3449 if (f.LocalPath().startswith('third_party') and
3450 not f.LocalPath().startswith('third_party/blink') and
3451 not f.LocalPath().startswith('third_party\\blink')):
3452 continue
3453
3454 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3455 continue
3456
3457 for _, line in f.ChangedContents():
3458 if line.startswith('#include "'):
3459 included_file = line.split('"')[1]
3460 if _IsCPlusPlusFile(input_api, included_file):
3461 # The most common naming for external files with C++ code,
3462 # apart from standard headers, is to call them foo.inc, but
3463 # Chromium sometimes uses foo-inc.cc so allow that as well.
3464 if not included_file.endswith(('.h', '-inc.cc')):
3465 results.append(output_api.PresubmitError(
3466 'Only header files or .inc files should be included in other\n'
3467 'C++ files. Compiling the contents of a cc file more than once\n'
3468 'will cause duplicate information in the build which may later\n'
3469 'result in strange link_errors.\n' +
3470 f.LocalPath() + ':\n ' +
3471 line))
3472
3473 return results
3474
3475
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203476def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3477 if not isinstance(key, ast.Str):
3478 return 'Key at line %d must be a string literal' % key.lineno
3479 if not isinstance(value, ast.Dict):
3480 return 'Value at line %d must be a dict' % value.lineno
3481 if len(value.keys) != 1:
3482 return 'Dict at line %d must have single entry' % value.lineno
3483 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3484 return (
3485 'Entry at line %d must have a string literal \'filepath\' as key' %
3486 value.lineno)
3487 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133488
Takeshi Yoshinoe387aa32017-08-02 13:16:133489
Sergey Ulanov4af16052018-11-08 02:41:463490def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203491 if not isinstance(key, ast.Str):
3492 return 'Key at line %d must be a string literal' % key.lineno
3493 if not isinstance(value, ast.List):
3494 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463495 for element in value.elts:
3496 if not isinstance(element, ast.Str):
3497 return 'Watchlist elements on line %d is not a string' % key.lineno
3498 if not email_regex.match(element.s):
3499 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3500 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203501 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133502
Takeshi Yoshinoe387aa32017-08-02 13:16:133503
Sergey Ulanov4af16052018-11-08 02:41:463504def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203505 mismatch_template = (
3506 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3507 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133508
Sergey Ulanov4af16052018-11-08 02:41:463509 email_regex = input_api.re.compile(
3510 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3511
3512 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203513 i = 0
3514 last_key = ''
3515 while True:
3516 if i >= len(wd_dict.keys):
3517 if i >= len(w_dict.keys):
3518 return None
3519 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3520 elif i >= len(w_dict.keys):
3521 return (
3522 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133523
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203524 wd_key = wd_dict.keys[i]
3525 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133526
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203527 result = _CheckWatchlistDefinitionsEntrySyntax(
3528 wd_key, wd_dict.values[i], ast)
3529 if result is not None:
3530 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133531
Sergey Ulanov4af16052018-11-08 02:41:463532 result = _CheckWatchlistsEntrySyntax(
3533 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203534 if result is not None:
3535 return 'Bad entry in WATCHLISTS dict: %s' % result
3536
3537 if wd_key.s != w_key.s:
3538 return mismatch_template % (
3539 '%s at line %d' % (wd_key.s, wd_key.lineno),
3540 '%s at line %d' % (w_key.s, w_key.lineno))
3541
3542 if wd_key.s < last_key:
3543 return (
3544 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3545 (wd_key.lineno, w_key.lineno))
3546 last_key = wd_key.s
3547
3548 i = i + 1
3549
3550
Sergey Ulanov4af16052018-11-08 02:41:463551def _CheckWATCHLISTSSyntax(expression, input_api):
3552 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203553 if not isinstance(expression, ast.Expression):
3554 return 'WATCHLISTS file must contain a valid expression'
3555 dictionary = expression.body
3556 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3557 return 'WATCHLISTS file must have single dict with exactly two entries'
3558
3559 first_key = dictionary.keys[0]
3560 first_value = dictionary.values[0]
3561 second_key = dictionary.keys[1]
3562 second_value = dictionary.values[1]
3563
3564 if (not isinstance(first_key, ast.Str) or
3565 first_key.s != 'WATCHLIST_DEFINITIONS' or
3566 not isinstance(first_value, ast.Dict)):
3567 return (
3568 'The first entry of the dict in WATCHLISTS file must be '
3569 'WATCHLIST_DEFINITIONS dict')
3570
3571 if (not isinstance(second_key, ast.Str) or
3572 second_key.s != 'WATCHLISTS' or
3573 not isinstance(second_value, ast.Dict)):
3574 return (
3575 'The second entry of the dict in WATCHLISTS file must be '
3576 'WATCHLISTS dict')
3577
Sergey Ulanov4af16052018-11-08 02:41:463578 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133579
3580
3581def _CheckWATCHLISTS(input_api, output_api):
3582 for f in input_api.AffectedFiles(include_deletes=False):
3583 if f.LocalPath() == 'WATCHLISTS':
3584 contents = input_api.ReadFile(f, 'r')
3585
3586 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203587 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133588 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203589 # Get an AST tree for it and scan the tree for detailed style checking.
3590 expression = input_api.ast.parse(
3591 contents, filename='WATCHLISTS', mode='eval')
3592 except ValueError as e:
3593 return [output_api.PresubmitError(
3594 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3595 except SyntaxError as e:
3596 return [output_api.PresubmitError(
3597 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3598 except TypeError as e:
3599 return [output_api.PresubmitError(
3600 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133601
Sergey Ulanov4af16052018-11-08 02:41:463602 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203603 if result is not None:
3604 return [output_api.PresubmitError(result)]
3605 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133606
3607 return []
3608
3609
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193610def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3611 """Checks that newly added header files have corresponding GN changes.
3612 Note that this is only a heuristic. To be precise, run script:
3613 build/check_gn_headers.py.
3614 """
3615
3616 def headers(f):
3617 return input_api.FilterSourceFile(
3618 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3619
3620 new_headers = []
3621 for f in input_api.AffectedSourceFiles(headers):
3622 if f.Action() != 'A':
3623 continue
3624 new_headers.append(f.LocalPath())
3625
3626 def gn_files(f):
3627 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3628
3629 all_gn_changed_contents = ''
3630 for f in input_api.AffectedSourceFiles(gn_files):
3631 for _, line in f.ChangedContents():
3632 all_gn_changed_contents += line
3633
3634 problems = []
3635 for header in new_headers:
3636 basename = input_api.os_path.basename(header)
3637 if basename not in all_gn_changed_contents:
3638 problems.append(header)
3639
3640 if problems:
3641 return [output_api.PresubmitPromptWarning(
3642 'Missing GN changes for new header files', items=sorted(problems),
3643 long_text='Please double check whether newly added header files need '
3644 'corresponding changes in gn or gni files.\nThis checking is only a '
3645 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3646 'Read https://crbug.com/661774 for more info.')]
3647 return []
3648
3649
Michael Giuffridad3bc8672018-10-25 22:48:023650def _CheckCorrectProductNameInMessages(input_api, output_api):
3651 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3652
3653 This assumes we won't intentionally reference one product from the other
3654 product.
3655 """
3656 all_problems = []
3657 test_cases = [{
3658 "filename_postfix": "google_chrome_strings.grd",
3659 "correct_name": "Chrome",
3660 "incorrect_name": "Chromium",
3661 }, {
3662 "filename_postfix": "chromium_strings.grd",
3663 "correct_name": "Chromium",
3664 "incorrect_name": "Chrome",
3665 }]
3666
3667 for test_case in test_cases:
3668 problems = []
3669 filename_filter = lambda x: x.LocalPath().endswith(
3670 test_case["filename_postfix"])
3671
3672 # Check each new line. Can yield false positives in multiline comments, but
3673 # easier than trying to parse the XML because messages can have nested
3674 # children, and associating message elements with affected lines is hard.
3675 for f in input_api.AffectedSourceFiles(filename_filter):
3676 for line_num, line in f.ChangedContents():
3677 if "<message" in line or "<!--" in line or "-->" in line:
3678 continue
3679 if test_case["incorrect_name"] in line:
3680 problems.append(
3681 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3682
3683 if problems:
3684 message = (
3685 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3686 % (test_case["correct_name"], test_case["correct_name"],
3687 test_case["incorrect_name"]))
3688 all_problems.append(
3689 output_api.PresubmitPromptWarning(message, items=problems))
3690
3691 return all_problems
3692
3693
Dirk Pranke3c18a382019-03-15 01:07:513694def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3695 # TODO(crbug.com/941824): We need to make sure the entries in
3696 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3697 # so that users of //buildtools in other projects get the same tooling
3698 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3699 # support to gclient, we can eliminate the duplication and delete
3700 # this presubmit check.
3701
3702 # Update this regexp if new revisions are added to the files.
3703 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013704 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513705
3706 # If a user is changing one revision, they need to change the same
3707 # line in both files. This means that any given change should contain
3708 # exactly the same list of changed lines that match the regexps. The
3709 # replace(' ', '') call allows us to ignore whitespace changes to the
3710 # lines. The 'long_text' parameter to the error will contain the
3711 # list of changed lines in both files, which should make it easy enough
3712 # to spot the error without going overboard in this implementation.
3713 revs_changes = {
3714 'DEPS': {},
3715 'buildtools/DEPS': {},
3716 }
3717 long_text = ''
3718
3719 for f in input_api.AffectedFiles(
3720 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3721 for line_num, line in f.ChangedContents():
3722 if rev_regexp.search(line):
3723 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3724 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3725
3726 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3727 return [output_api.PresubmitError(
3728 'Change buildtools revisions in sync in both //DEPS and '
3729 '//buildtools/DEPS.', long_text=long_text + '\n')]
3730 else:
3731 return []
3732
3733
Daniel Bratell93eb6c62019-04-29 20:13:363734def _CheckForTooLargeFiles(input_api, output_api):
3735 """Avoid large files, especially binary files, in the repository since
3736 git doesn't scale well for those. They will be in everyone's repo
3737 clones forever, forever making Chromium slower to clone and work
3738 with."""
3739
3740 # Uploading files to cloud storage is not trivial so we don't want
3741 # to set the limit too low, but the upper limit for "normal" large
3742 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
3743 # anything over 20 MB is exceptional.
3744 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
3745
3746 too_large_files = []
3747 for f in input_api.AffectedFiles():
3748 # Check both added and modified files (but not deleted files).
3749 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:383750 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:363751 if size > TOO_LARGE_FILE_SIZE_LIMIT:
3752 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
3753
3754 if too_large_files:
3755 message = (
3756 'Do not commit large files to git since git scales badly for those.\n' +
3757 'Instead put the large files in cloud storage and use DEPS to\n' +
3758 'fetch them.\n' + '\n'.join(too_large_files)
3759 )
3760 return [output_api.PresubmitError(
3761 'Too large files found in commit', long_text=message + '\n')]
3762 else:
3763 return []
3764
dgnaa68d5e2015-06-10 10:08:223765def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:573766 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:223767 results = []
dgnaa68d5e2015-06-10 10:08:223768 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:173769 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:223770 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:293771 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:063772 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
3773 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:423774 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:183775 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:573776 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
3777 return results
3778
3779def _AndroidSpecificOnCommitChecks(input_api, output_api):
3780 """Groups commit checks that target android code."""
3781 results = []
3782 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:223783 return results
3784
3785
[email protected]22c9bd72011-03-27 16:47:393786def _CommonChecks(input_api, output_api):
3787 """Checks common to both upload and commit."""
3788 results = []
3789 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:383790 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:543791 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:083792
3793 author = input_api.change.author_email
3794 if author and author not in _KNOWN_ROBOTS:
3795 results.extend(
3796 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
3797
[email protected]55459852011-08-10 15:17:193798 results.extend(
[email protected]760deea2013-12-10 19:33:493799 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:233800 results.extend(
3801 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:543802 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:183803 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:343804 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:523805 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:223806 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:443807 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:593808 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:063809 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:123810 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:183811 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:223812 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:303813 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:493814 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:033815 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:493816 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:443817 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:273818 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:073819 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:543820 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:443821 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:393822 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:553823 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:043824 results.extend(
3825 input_api.canned_checks.CheckChangeHasNoTabs(
3826 input_api,
3827 output_api,
3828 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:403829 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:163830 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:083831 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:243832 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:473833 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:043834 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:053835 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:143836 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:233837 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:433838 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:403839 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:153840 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:173841 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:503842 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:363843 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:063844 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:133845 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:433846 results.extend(input_api.RunTests(
3847 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:143848 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:023849 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:513850 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:363851 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:003852 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:243853
Vaclav Brozekcdc7defb2018-03-20 09:54:353854 for f in input_api.AffectedFiles():
3855 path, name = input_api.os_path.split(f.LocalPath())
3856 if name == 'PRESUBMIT.py':
3857 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:003858 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
3859 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:073860 # The PRESUBMIT.py file (and the directory containing it) might
3861 # have been affected by being moved or removed, so only try to
3862 # run the tests if they still exist.
3863 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
3864 input_api, output_api, full_path,
3865 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:393866 return results
[email protected]1f7b4172010-01-28 01:17:343867
[email protected]b337cb5b2011-01-23 21:24:053868
[email protected]b8079ae4a2012-12-05 19:56:493869def _CheckPatchFiles(input_api, output_api):
3870 problems = [f.LocalPath() for f in input_api.AffectedFiles()
3871 if f.LocalPath().endswith(('.orig', '.rej'))]
3872 if problems:
3873 return [output_api.PresubmitError(
3874 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:033875 else:
3876 return []
[email protected]b8079ae4a2012-12-05 19:56:493877
3878
Kent Tamura5a8755d2017-06-29 23:37:073879def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:213880 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
3881 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
3882 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:073883 include_re = input_api.re.compile(
3884 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
3885 extension_re = input_api.re.compile(r'\.[a-z]+$')
3886 errors = []
3887 for f in input_api.AffectedFiles():
3888 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
3889 continue
3890 found_line_number = None
3891 found_macro = None
3892 for line_num, line in f.ChangedContents():
3893 match = macro_re.search(line)
3894 if match:
3895 found_line_number = line_num
3896 found_macro = match.group(2)
3897 break
3898 if not found_line_number:
3899 continue
3900
3901 found_include = False
3902 for line in f.NewContents():
3903 if include_re.search(line):
3904 found_include = True
3905 break
3906 if found_include:
3907 continue
3908
3909 if not f.LocalPath().endswith('.h'):
3910 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
3911 try:
3912 content = input_api.ReadFile(primary_header_path, 'r')
3913 if include_re.search(content):
3914 continue
3915 except IOError:
3916 pass
3917 errors.append('%s:%d %s macro is used without including build/'
3918 'build_config.h.'
3919 % (f.LocalPath(), found_line_number, found_macro))
3920 if errors:
3921 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
3922 return []
3923
3924
[email protected]b00342e7f2013-03-26 16:21:543925def _DidYouMeanOSMacro(bad_macro):
3926 try:
3927 return {'A': 'OS_ANDROID',
3928 'B': 'OS_BSD',
3929 'C': 'OS_CHROMEOS',
3930 'F': 'OS_FREEBSD',
3931 'L': 'OS_LINUX',
3932 'M': 'OS_MACOSX',
3933 'N': 'OS_NACL',
3934 'O': 'OS_OPENBSD',
3935 'P': 'OS_POSIX',
3936 'S': 'OS_SOLARIS',
3937 'W': 'OS_WIN'}[bad_macro[3].upper()]
3938 except KeyError:
3939 return ''
3940
3941
3942def _CheckForInvalidOSMacrosInFile(input_api, f):
3943 """Check for sensible looking, totally invalid OS macros."""
3944 preprocessor_statement = input_api.re.compile(r'^\s*#')
3945 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
3946 results = []
3947 for lnum, line in f.ChangedContents():
3948 if preprocessor_statement.search(line):
3949 for match in os_macro.finditer(line):
3950 if not match.group(1) in _VALID_OS_MACROS:
3951 good = _DidYouMeanOSMacro(match.group(1))
3952 did_you_mean = ' (did you mean %s?)' % good if good else ''
3953 results.append(' %s:%d %s%s' % (f.LocalPath(),
3954 lnum,
3955 match.group(1),
3956 did_you_mean))
3957 return results
3958
3959
3960def _CheckForInvalidOSMacros(input_api, output_api):
3961 """Check all affected files for invalid OS macros."""
3962 bad_macros = []
tzik3f295992018-12-04 20:32:233963 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:473964 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:543965 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
3966
3967 if not bad_macros:
3968 return []
3969
3970 return [output_api.PresubmitError(
3971 'Possibly invalid OS macro[s] found. Please fix your code\n'
3972 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
3973
lliabraa35bab3932014-10-01 12:16:443974
3975def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
3976 """Check all affected files for invalid "if defined" macros."""
3977 ALWAYS_DEFINED_MACROS = (
3978 "TARGET_CPU_PPC",
3979 "TARGET_CPU_PPC64",
3980 "TARGET_CPU_68K",
3981 "TARGET_CPU_X86",
3982 "TARGET_CPU_ARM",
3983 "TARGET_CPU_MIPS",
3984 "TARGET_CPU_SPARC",
3985 "TARGET_CPU_ALPHA",
3986 "TARGET_IPHONE_SIMULATOR",
3987 "TARGET_OS_EMBEDDED",
3988 "TARGET_OS_IPHONE",
3989 "TARGET_OS_MAC",
3990 "TARGET_OS_UNIX",
3991 "TARGET_OS_WIN32",
3992 )
3993 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
3994 results = []
3995 for lnum, line in f.ChangedContents():
3996 for match in ifdef_macro.finditer(line):
3997 if match.group(1) in ALWAYS_DEFINED_MACROS:
3998 always_defined = ' %s is always defined. ' % match.group(1)
3999 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4000 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4001 lnum,
4002 always_defined,
4003 did_you_mean))
4004 return results
4005
4006
4007def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4008 """Check all affected files for invalid "if defined" macros."""
4009 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054010 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444011 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054012 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214013 continue
lliabraa35bab3932014-10-01 12:16:444014 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4015 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4016
4017 if not bad_macros:
4018 return []
4019
4020 return [output_api.PresubmitError(
4021 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4022 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4023 bad_macros)]
4024
4025
mlamouria82272622014-09-16 18:45:044026def _CheckForIPCRules(input_api, output_api):
4027 """Check for same IPC rules described in
4028 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4029 """
4030 base_pattern = r'IPC_ENUM_TRAITS\('
4031 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4032 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4033
4034 problems = []
4035 for f in input_api.AffectedSourceFiles(None):
4036 local_path = f.LocalPath()
4037 if not local_path.endswith('.h'):
4038 continue
4039 for line_number, line in f.ChangedContents():
4040 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4041 problems.append(
4042 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4043
4044 if problems:
4045 return [output_api.PresubmitPromptWarning(
4046 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4047 else:
4048 return []
4049
[email protected]b00342e7f2013-03-26 16:21:544050
Stephen Martinis97a394142018-06-07 23:06:054051def _CheckForLongPathnames(input_api, output_api):
4052 """Check to make sure no files being submitted have long paths.
4053 This causes issues on Windows.
4054 """
4055 problems = []
4056 for f in input_api.AffectedSourceFiles(None):
4057 local_path = f.LocalPath()
4058 # Windows has a path limit of 260 characters. Limit path length to 200 so
4059 # that we have some extra for the prefix on dev machines and the bots.
4060 if len(local_path) > 200:
4061 problems.append(local_path)
4062
4063 if problems:
4064 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4065 else:
4066 return []
4067
4068
Daniel Bratell8ba52722018-03-02 16:06:144069def _CheckForIncludeGuards(input_api, output_api):
4070 """Check that header files have proper guards against multiple inclusion.
4071 If a file should not have such guards (and it probably should) then it
4072 should include the string "no-include-guard-because-multiply-included".
4073 """
Daniel Bratell6a75baef62018-06-04 10:04:454074 def is_chromium_header_file(f):
4075 # We only check header files under the control of the Chromium
4076 # project. That is, those outside third_party apart from
4077 # third_party/blink.
4078 file_with_path = input_api.os_path.normpath(f.LocalPath())
4079 return (file_with_path.endswith('.h') and
4080 (not file_with_path.startswith('third_party') or
4081 file_with_path.startswith(
4082 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144083
4084 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344085 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144086
4087 errors = []
4088
Daniel Bratell6a75baef62018-06-04 10:04:454089 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144090 guard_name = None
4091 guard_line_number = None
4092 seen_guard_end = False
4093
4094 file_with_path = input_api.os_path.normpath(f.LocalPath())
4095 base_file_name = input_api.os_path.splitext(
4096 input_api.os_path.basename(file_with_path))[0]
4097 upper_base_file_name = base_file_name.upper()
4098
4099 expected_guard = replace_special_with_underscore(
4100 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144101
4102 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574103 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4104 # are too many (1000+) files with slight deviations from the
4105 # coding style. The most important part is that the include guard
4106 # is there, and that it's unique, not the name so this check is
4107 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144108 #
4109 # As code becomes more uniform, this could be made stricter.
4110
4111 guard_name_pattern_list = [
4112 # Anything with the right suffix (maybe with an extra _).
4113 r'\w+_H__?',
4114
Daniel Bratell39b5b062018-05-16 18:09:574115 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144116 r'\w+_h',
4117
4118 # Anything including the uppercase name of the file.
4119 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4120 upper_base_file_name)) + r'\w*',
4121 ]
4122 guard_name_pattern = '|'.join(guard_name_pattern_list)
4123 guard_pattern = input_api.re.compile(
4124 r'#ifndef\s+(' + guard_name_pattern + ')')
4125
4126 for line_number, line in enumerate(f.NewContents()):
4127 if 'no-include-guard-because-multiply-included' in line:
4128 guard_name = 'DUMMY' # To not trigger check outside the loop.
4129 break
4130
4131 if guard_name is None:
4132 match = guard_pattern.match(line)
4133 if match:
4134 guard_name = match.group(1)
4135 guard_line_number = line_number
4136
Daniel Bratell39b5b062018-05-16 18:09:574137 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454138 # don't match the chromium style guide, but new files should
4139 # get it right.
4140 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574141 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144142 errors.append(output_api.PresubmitPromptWarning(
4143 'Header using the wrong include guard name %s' % guard_name,
4144 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Daniel Bratell39b5b062018-05-16 18:09:574145 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144146 else:
4147 # The line after #ifndef should have a #define of the same name.
4148 if line_number == guard_line_number + 1:
4149 expected_line = '#define %s' % guard_name
4150 if line != expected_line:
4151 errors.append(output_api.PresubmitPromptWarning(
4152 'Missing "%s" for include guard' % expected_line,
4153 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4154 'Expected: %r\nGot: %r' % (expected_line, line)))
4155
4156 if not seen_guard_end and line == '#endif // %s' % guard_name:
4157 seen_guard_end = True
4158 elif seen_guard_end:
4159 if line.strip() != '':
4160 errors.append(output_api.PresubmitPromptWarning(
4161 'Include guard %s not covering the whole file' % (
4162 guard_name), [f.LocalPath()]))
4163 break # Nothing else to check and enough to warn once.
4164
4165 if guard_name is None:
4166 errors.append(output_api.PresubmitPromptWarning(
4167 'Missing include guard %s' % expected_guard,
4168 [f.LocalPath()],
4169 'Missing include guard in %s\n'
4170 'Recommended name: %s\n'
4171 'This check can be disabled by having the string\n'
4172 'no-include-guard-because-multiply-included in the header.' %
4173 (f.LocalPath(), expected_guard)))
4174
4175 return errors
4176
4177
mostynbb639aca52015-01-07 20:31:234178def _CheckForWindowsLineEndings(input_api, output_api):
4179 """Check source code and known ascii text files for Windows style line
4180 endings.
4181 """
earthdok1b5e0ee2015-03-10 15:19:104182 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234183
4184 file_inclusion_pattern = (
4185 known_text_files,
4186 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4187 )
4188
mostynbb639aca52015-01-07 20:31:234189 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534190 source_file_filter = lambda f: input_api.FilterSourceFile(
4191 f, white_list=file_inclusion_pattern, black_list=None)
4192 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504193 include_file = False
4194 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234195 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504196 include_file = True
4197 if include_file:
4198 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234199
4200 if problems:
4201 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4202 'these files to contain Windows style line endings?\n' +
4203 '\n'.join(problems))]
4204
4205 return []
4206
4207
Vaclav Brozekd5de76a2018-03-17 07:57:504208def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134209 """Checks that all source files use SYSLOG properly."""
4210 syslog_files = []
4211 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564212 for line_number, line in f.ChangedContents():
4213 if 'SYSLOG' in line:
4214 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4215
pastarmovj89f7ee12016-09-20 14:58:134216 if syslog_files:
4217 return [output_api.PresubmitPromptWarning(
4218 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4219 ' calls.\nFiles to check:\n', items=syslog_files)]
4220 return []
4221
4222
[email protected]1f7b4172010-01-28 01:17:344223def CheckChangeOnUpload(input_api, output_api):
4224 results = []
4225 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474226 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284227 results.extend(
jam93a6ee792017-02-08 23:59:224228 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194229 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224230 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134231 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164232 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534233 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194234 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544235 return results
[email protected]ca8d1982009-02-19 16:33:124236
4237
[email protected]1bfb8322014-04-23 01:02:414238def GetTryServerMasterForBot(bot):
4239 """Returns the Try Server master for the given bot.
4240
[email protected]0bb112362014-07-26 04:38:324241 It tries to guess the master from the bot name, but may still fail
4242 and return None. There is no longer a default master.
4243 """
4244 # Potentially ambiguous bot names are listed explicitly.
4245 master_map = {
tandriie5587792016-07-14 00:34:504246 'chromium_presubmit': 'master.tryserver.chromium.linux',
4247 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414248 }
[email protected]0bb112362014-07-26 04:38:324249 master = master_map.get(bot)
4250 if not master:
wnwen4fbaab82016-05-25 12:54:364251 if 'android' in bot:
tandriie5587792016-07-14 00:34:504252 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364253 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504254 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324255 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504256 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324257 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504258 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324259 return master
[email protected]1bfb8322014-04-23 01:02:414260
4261
[email protected]ca8d1982009-02-19 16:33:124262def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544263 results = []
[email protected]1f7b4172010-01-28 01:17:344264 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574265 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544266 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274267 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344268 input_api,
4269 output_api,
[email protected]2fdd1f362013-01-16 03:56:034270 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274271
jam93a6ee792017-02-08 23:59:224272 results.extend(
4273 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544274 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4275 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414276 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4277 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544278 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144279
4280
4281def _CheckTranslationScreenshots(input_api, output_api):
4282 PART_FILE_TAG = "part"
4283 import os
4284 import sys
4285 from io import StringIO
4286
4287 try:
4288 old_sys_path = sys.path
4289 sys.path = sys.path + [input_api.os_path.join(
4290 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4291 import grit.grd_reader
4292 import grit.node.message
4293 import grit.util
4294 finally:
4295 sys.path = old_sys_path
4296
4297 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4298 """Load the grd file and return a dict of message ids to messages.
4299
4300 Ignores any nested grdp files pointed by <part> tag.
4301 """
4302 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4303 stop_after=None, first_ids_file=None,
Julian Pastarmov4f7af532019-07-17 19:25:374304 debug=False, defines={'_chromium': 1},
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144305 tags_to_ignore=set([PART_FILE_TAG]))
4306 return {
4307 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4308 grit.node.message.MessageNode)
4309 }
4310
4311 def _GetGrdpMessagesFromString(grdp_string):
4312 """Parses the contents of a grdp file given in grdp_string.
4313
4314 grd_reader can't parse grdp files directly. Instead, this creates a
4315 temporary directory with a grd file pointing to the grdp file, and loads the
4316 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4317 """
4318 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4319 <grit latest_public_release="1" current_release="1">
4320 <release seq="1">
4321 <messages>
4322 <part file="sub.grdp" />
4323 </messages>
4324 </release>
4325 </grit>
4326 """
4327 with grit.util.TempDir({'main.grd': WRAPPER,
4328 'sub.grdp': grdp_string}) as temp_dir:
4329 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4330
4331 new_or_added_paths = set(f.LocalPath()
4332 for f in input_api.AffectedFiles()
4333 if (f.Action() == 'A' or f.Action() == 'M'))
4334 removed_paths = set(f.LocalPath()
4335 for f in input_api.AffectedFiles(include_deletes=True)
4336 if f.Action() == 'D')
4337
4338 affected_grds = [f for f in input_api.AffectedFiles()
4339 if (f.LocalPath().endswith('.grd') or
4340 f.LocalPath().endswith('.grdp'))]
4341 affected_png_paths = [f.AbsoluteLocalPath()
4342 for f in input_api.AffectedFiles()
4343 if (f.LocalPath().endswith('.png'))]
4344
4345 # Check for screenshots. Developers can upload screenshots using
4346 # tools/translation/upload_screenshots.py which finds and uploads
4347 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4348 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4349 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4350 #
4351 # The logic here is as follows:
4352 #
4353 # - If the CL has a .png file under the screenshots directory for a grd
4354 # file, warn the developer. Actual images should never be checked into the
4355 # Chrome repo.
4356 #
4357 # - If the CL contains modified or new messages in grd files and doesn't
4358 # contain the corresponding .sha1 files, warn the developer to add images
4359 # and upload them via tools/translation/upload_screenshots.py.
4360 #
4361 # - If the CL contains modified or new messages in grd files and the
4362 # corresponding .sha1 files, everything looks good.
4363 #
4364 # - If the CL contains removed messages in grd files but the corresponding
4365 # .sha1 files aren't removed, warn the developer to remove them.
4366 unnecessary_screenshots = []
4367 missing_sha1 = []
4368 unnecessary_sha1_files = []
4369
4370
4371 def _CheckScreenshotAdded(screenshots_dir, message_id):
4372 sha1_path = input_api.os_path.join(
4373 screenshots_dir, message_id + '.png.sha1')
4374 if sha1_path not in new_or_added_paths:
4375 missing_sha1.append(sha1_path)
4376
4377
4378 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4379 sha1_path = input_api.os_path.join(
4380 screenshots_dir, message_id + '.png.sha1')
4381 if sha1_path not in removed_paths:
4382 unnecessary_sha1_files.append(sha1_path)
4383
4384
4385 for f in affected_grds:
4386 file_path = f.LocalPath()
4387 old_id_to_msg_map = {}
4388 new_id_to_msg_map = {}
4389 if file_path.endswith('.grdp'):
4390 if f.OldContents():
4391 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394392 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144393 if f.NewContents():
4394 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394395 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144396 else:
4397 if f.OldContents():
4398 old_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394399 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144400 if f.NewContents():
4401 new_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394402 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144403
4404 # Compute added, removed and modified message IDs.
4405 old_ids = set(old_id_to_msg_map)
4406 new_ids = set(new_id_to_msg_map)
4407 added_ids = new_ids - old_ids
4408 removed_ids = old_ids - new_ids
4409 modified_ids = set([])
4410 for key in old_ids.intersection(new_ids):
4411 if (old_id_to_msg_map[key].FormatXml()
4412 != new_id_to_msg_map[key].FormatXml()):
4413 modified_ids.add(key)
4414
4415 grd_name, ext = input_api.os_path.splitext(
4416 input_api.os_path.basename(file_path))
4417 screenshots_dir = input_api.os_path.join(
4418 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4419
4420 # Check the screenshot directory for .png files. Warn if there is any.
4421 for png_path in affected_png_paths:
4422 if png_path.startswith(screenshots_dir):
4423 unnecessary_screenshots.append(png_path)
4424
4425 for added_id in added_ids:
4426 _CheckScreenshotAdded(screenshots_dir, added_id)
4427
4428 for modified_id in modified_ids:
4429 _CheckScreenshotAdded(screenshots_dir, modified_id)
4430
4431 for removed_id in removed_ids:
4432 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4433
4434 results = []
4435 if unnecessary_screenshots:
4436 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394437 'Do not include actual screenshots in the changelist. Run '
4438 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144439 sorted(unnecessary_screenshots)))
4440
4441 if missing_sha1:
4442 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394443 'You are adding or modifying UI strings.\n'
4444 'To ensure the best translations, take screenshots of the relevant UI '
4445 '(https://g.co/chrome/translation) and add these files to your '
4446 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144447
4448 if unnecessary_sha1_files:
4449 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394450 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144451 sorted(unnecessary_sha1_files)))
4452
4453 return results