blob: 125fb20ed3edd2fa932db42396efe23cebdd3b1c [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0413 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py",
14 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py",
15 r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
16 r"^net[\\/]tools[\\/]spdyshark[\\/].*",
17 r"^skia[\\/].*",
Kent Tamura32dbbcb2018-11-30 12:28:4918 r"^third_party[\\/]blink[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0419 r"^third_party[\\/]breakpad[\\/].*",
Darwin Huangd74a9d32019-07-17 17:58:4620 # sqlite is an imported third party dependency.
21 r"^third_party[\\/]sqlite[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0422 r"^v8[\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5324 r".+_autogen\.h$",
John Budorick1e701d322019-09-11 23:35:1225 r".+_pb2\.py$",
Egor Paskoce145c42018-09-28 19:31:0426 r".+[\\/]pnacl_shim\.c$",
27 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
28 r"^chrome[\\/]browser[\\/]resources[\\/]pdf[\\/]index.js",
29 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1430 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0431 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5432 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0433 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4034)
[email protected]ca8d1982009-02-19 16:33:1235
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Fragment of a regular expression that matches C++ and Objective-C++
38# implementation files.
39_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
40
wnwenbdc444e2016-05-25 13:44:1541
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1942# Fragment of a regular expression that matches C++ and Objective-C++
43# header files.
44_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
45
46
[email protected]06e6d0ff2012-12-11 01:36:4447# Regular expression that matches code only used for test binaries
48# (best effort).
49_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0450 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4452 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1253 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1854 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4455 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0456 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0557 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0458 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4759 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0460 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0861 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0462 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4163 # EarlGrey app side code for tests.
64 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4465)
[email protected]ca8d1982009-02-19 16:33:1266
Daniel Bratell609102be2019-03-27 20:53:2167_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1568
[email protected]eea609a2011-11-18 13:10:1269_TEST_ONLY_WARNING = (
70 'You might be calling functions intended only for testing from\n'
71 'production code. It is OK to ignore this warning if you know what\n'
72 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0773 'not perfect. The commit queue will not block on this warning,\n'
74 'however the android-binary-size trybot will block if the method\n'
75 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1276
77
[email protected]cf9b78f2012-11-14 11:40:2878_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4079 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2180 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
81 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2882
wnwenbdc444e2016-05-25 13:44:1583
Daniel Bratell609102be2019-03-27 20:53:2184# Format: Sequence of tuples containing:
85# * String pattern or, if starting with a slash, a regular expression.
86# * Sequence of strings to show when the pattern matches.
87# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:4188_BANNED_JAVA_FUNCTIONS = (
89 (
90 'StrictMode.allowThreadDiskReads()',
91 (
92 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
93 'directly.',
94 ),
95 False,
96 ),
97 (
98 'StrictMode.allowThreadDiskWrites()',
99 (
100 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
101 'directly.',
102 ),
103 False,
104 ),
105)
106
Daniel Bratell609102be2019-03-27 20:53:21107# Format: Sequence of tuples containing:
108# * String pattern or, if starting with a slash, a regular expression.
109# * Sequence of strings to show when the pattern matches.
110# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59111_BANNED_OBJC_FUNCTIONS = (
112 (
113 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59116 'prohibited. Please use CrTrackingArea instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 False,
120 ),
121 (
[email protected]eaae1972014-04-16 04:17:26122 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59125 'instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 False,
129 ),
130 (
131 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertPoint:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertPoint:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
148 (
149 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20150 (
151 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59152 'Please use |convertRect:(point) fromView:nil| instead.',
153 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
154 ),
155 True,
156 ),
157 (
158 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20159 (
160 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59161 'Please use |convertRect:(point) toView:nil| instead.',
162 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
163 ),
164 True,
165 ),
166 (
167 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20168 (
169 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59170 'Please use |convertSize:(point) fromView:nil| instead.',
171 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
172 ),
173 True,
174 ),
175 (
176 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20177 (
178 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59179 'Please use |convertSize:(point) toView:nil| instead.',
180 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
181 ),
182 True,
183 ),
jif65398702016-10-27 10:19:48184 (
185 r"/\s+UTF8String\s*]",
186 (
187 'The use of -[NSString UTF8String] is dangerous as it can return null',
188 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
189 'Please use |SysNSStringToUTF8| instead.',
190 ),
191 True,
192 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34193 (
194 r'__unsafe_unretained',
195 (
196 'The use of __unsafe_unretained is almost certainly wrong, unless',
197 'when interacting with NSFastEnumeration or NSInvocation.',
198 'Please use __weak in files build with ARC, nothing otherwise.',
199 ),
200 False,
201 ),
Avi Drissman7382afa02019-04-29 23:27:13202 (
203 'freeWhenDone:NO',
204 (
205 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
206 'Foundation types is prohibited.',
207 ),
208 True,
209 ),
[email protected]127f18ec2012-06-16 05:05:59210)
211
Daniel Bratell609102be2019-03-27 20:53:21212# Format: Sequence of tuples containing:
213# * String pattern or, if starting with a slash, a regular expression.
214# * Sequence of strings to show when the pattern matches.
215# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54216_BANNED_IOS_OBJC_FUNCTIONS = (
217 (
218 r'/\bTEST[(]',
219 (
220 'TEST() macro should not be used in Objective-C++ code as it does not ',
221 'drain the autorelease pool at the end of the test. Use TEST_F() ',
222 'macro instead with a fixture inheriting from PlatformTest (or a ',
223 'typedef).'
224 ),
225 True,
226 ),
227 (
228 r'/\btesting::Test\b',
229 (
230 'testing::Test should not be used in Objective-C++ code as it does ',
231 'not drain the autorelease pool at the end of the test. Use ',
232 'PlatformTest instead.'
233 ),
234 True,
235 ),
236)
237
Peter K. Lee6c03ccff2019-07-15 14:40:05238# Format: Sequence of tuples containing:
239# * String pattern or, if starting with a slash, a regular expression.
240# * Sequence of strings to show when the pattern matches.
241# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
242_BANNED_IOS_EGTEST_FUNCTIONS = (
243 (
244 r'/\bEXPECT_OCMOCK_VERIFY\b',
245 (
246 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
247 'it is meant for GTests. Use [mock verify] instead.'
248 ),
249 True,
250 ),
251)
252
danakj7a2b7082019-05-21 21:13:51253# Directories that contain deprecated Bind() or Callback types.
254# Find sub-directories from a given directory by running:
255# for i in `find . -maxdepth 1 -type d`; do
256# echo "-- $i"
257# (cd $i; git grep -P 'base::(Bind\(|(Callback<|Closure))'|wc -l)
258# done
259#
260# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
261# when they have been converted to modern callback types (OnceCallback,
262# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
263# checks for them and prevent regressions.
264_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
265 '^android_webview/browser/',
266 '^apps/',
267 '^ash/',
danakj7a2b7082019-05-21 21:13:51268 '^base/callback.h', # Intentional.
269 '^chrome/app/',
270 '^chrome/browser/',
271 '^chrome/chrome_elf/',
272 '^chrome/chrome_watcher/',
273 '^chrome/common/',
274 '^chrome/installer/',
275 '^chrome/notification_helper/',
276 '^chrome/renderer/',
277 '^chrome/services/',
278 '^chrome/test/',
279 '^chrome/tools/',
280 '^chrome/utility/',
281 '^chromecast/app/',
282 '^chromecast/browser/',
283 '^chromecast/crash/',
284 '^chromecast/media/',
285 '^chromecast/metrics/',
286 '^chromecast/net/',
287 '^chromeos/attestation/',
288 '^chromeos/audio/',
289 '^chromeos/components/',
290 '^chromeos/cryptohome/',
291 '^chromeos/dbus/',
292 '^chromeos/geolocation/',
293 '^chromeos/login/',
294 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51295 '^chromeos/process_proxy/',
296 '^chromeos/services/',
297 '^chromeos/settings/',
298 '^chromeos/timezone/',
299 '^chromeos/tpm/',
300 '^components/arc/',
301 '^components/assist_ranker/',
302 '^components/autofill/',
303 '^components/autofill_assistant/',
304 '^components/bookmarks/',
305 '^components/browser_sync/',
306 '^components/browser_watcher/',
307 '^components/browsing_data/',
308 '^components/cast_channel/',
309 '^components/certificate_transparency/',
310 '^components/chromeos_camera/',
311 '^components/component_updater/',
312 '^components/content_settings/',
313 '^components/crash/',
314 '^components/cronet/',
315 '^components/data_reduction_proxy/',
316 '^components/discardable_memory/',
317 '^components/dom_distiller/',
318 '^components/domain_reliability/',
319 '^components/download/',
320 '^components/drive/',
321 '^components/exo/',
322 '^components/favicon/',
323 '^components/feature_engagement/',
324 '^components/feedback/',
325 '^components/flags_ui/',
326 '^components/gcm_driver/',
327 '^components/google/',
328 '^components/guest_view/',
329 '^components/heap_profiling/',
330 '^components/history/',
331 '^components/image_fetcher/',
332 '^components/invalidation/',
333 '^components/keyed_service/',
334 '^components/login/',
335 '^components/metrics/',
336 '^components/metrics_services_manager/',
337 '^components/nacl/',
338 '^components/navigation_interception/',
339 '^components/net_log/',
340 '^components/network_time/',
341 '^components/ntp_snippets/',
342 '^components/ntp_tiles/',
343 '^components/offline_items_collection/',
344 '^components/offline_pages/',
345 '^components/omnibox/',
346 '^components/ownership/',
347 '^components/pairing/',
348 '^components/password_manager/',
349 '^components/payments/',
350 '^components/plugins/',
351 '^components/policy/',
352 '^components/pref_registry/',
353 '^components/prefs/',
danakj7a2b7082019-05-21 21:13:51354 '^components/proxy_config/',
355 '^components/quirks/',
356 '^components/rappor/',
357 '^components/remote_cocoa/',
358 '^components/renderer_context_menu/',
359 '^components/rlz/',
360 '^components/safe_browsing/',
361 '^components/search_engines/',
362 '^components/search_provider_logos/',
363 '^components/security_interstitials/',
364 '^components/security_state/',
365 '^components/services/',
366 '^components/sessions/',
367 '^components/signin/',
368 '^components/ssl_errors/',
369 '^components/storage_monitor/',
370 '^components/subresource_filter/',
371 '^components/suggestions/',
372 '^components/supervised_user_error_page/',
373 '^components/sync/',
374 '^components/sync_bookmarks/',
375 '^components/sync_device_info/',
376 '^components/sync_preferences/',
377 '^components/sync_sessions/',
378 '^components/test/',
379 '^components/tracing/',
380 '^components/translate/',
381 '^components/ukm/',
382 '^components/update_client/',
383 '^components/upload_list/',
384 '^components/variations/',
385 '^components/visitedlink/',
386 '^components/web_cache/',
danakj7a2b7082019-05-21 21:13:51387 '^components/webcrypto/',
388 '^components/webdata/',
389 '^components/webdata_services/',
390 '^components/wifi/',
391 '^components/zoom/',
392 '^content/app/',
393 '^content/browser/',
394 '^content/child/',
395 '^content/common/',
396 '^content/public/',
397 '^content/renderer/android/',
398 '^content/renderer/fetchers/',
399 '^content/renderer/image_downloader/',
400 '^content/renderer/input/',
401 '^content/renderer/java/',
402 '^content/renderer/media/',
403 '^content/renderer/media_capture_from_element/',
404 '^content/renderer/media_recorder/',
405 '^content/renderer/p2p/',
406 '^content/renderer/pepper/',
407 '^content/renderer/service_worker/',
408 '^content/renderer/worker/',
409 '^content/test/',
410 '^content/utility/',
411 '^dbus/',
412 '^device/base/',
413 '^device/bluetooth/',
414 '^device/fido/',
415 '^device/gamepad/',
danakj7a2b7082019-05-21 21:13:51416 '^device/vr/',
417 '^extensions/',
418 '^gin/',
419 '^google_apis/dive/',
420 '^google_apis/gaia/',
421 '^google_apis/gcm/',
422 '^headless/',
423 '^ios/chrome/',
424 '^ios/components/',
425 '^ios/net/',
426 '^ios/web/',
427 '^ios/web_view/',
428 '^ipc/',
429 '^media/audio/',
430 '^media/base/',
431 '^media/capture/',
432 '^media/cast/',
433 '^media/cdm/',
434 '^media/device_monitors/',
435 '^media/ffmpeg/',
436 '^media/filters/',
437 '^media/formats/',
438 '^media/gpu/',
439 '^media/mojo/',
440 '^media/muxers/',
441 '^media/remoting/',
442 '^media/renderers/',
443 '^media/test/',
444 '^mojo/core/',
445 '^mojo/public/',
446 '^net/',
447 '^ppapi/proxy/',
448 '^ppapi/shared_impl/',
449 '^ppapi/tests/',
450 '^ppapi/thunk/',
451 '^remoting/base/',
452 '^remoting/client/',
453 '^remoting/codec/',
454 '^remoting/host/',
455 '^remoting/internal/',
456 '^remoting/ios/',
457 '^remoting/protocol/',
458 '^remoting/signaling/',
459 '^remoting/test/',
460 '^sandbox/linux/',
461 '^sandbox/win/',
462 '^services/',
463 '^storage/browser/',
danakj7a2b7082019-05-21 21:13:51464 '^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 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20501 False,
thomasandersone7caaa9b2017-03-29 19:22:53502 (),
503 ),
Peter Kasting94a56c42019-10-25 21:54:04504 (
505 r'/\busing namespace ',
506 (
507 'Using directives ("using namespace x") are banned by the Google Style',
508 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
509 'Explicitly qualify symbols or use using declarations ("using x::foo").',
510 ),
511 True,
512 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
513 ),
Antonio Gomes07300d02019-03-13 20:59:57514 # Make sure that gtest's FRIEND_TEST() macro is not used; the
515 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
516 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53517 (
[email protected]23e6cbc2012-06-16 18:51:20518 'FRIEND_TEST(',
519 (
[email protected]e3c945502012-06-26 20:01:49520 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20521 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
522 ),
523 False,
[email protected]7345da02012-11-27 14:31:49524 (),
[email protected]23e6cbc2012-06-16 18:51:20525 ),
526 (
Dave Tapuska98199b612019-07-10 13:30:44527 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53528 (
529 'Chrome clients wishing to select events on X windows should use',
530 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
531 'you are selecting events from the GPU process, or if you are using',
532 'an XDisplay other than gfx::GetXDisplay().',
533 ),
534 True,
535 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40536 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04537 r"^ui[\\/]gl[\\/].*\.cc$",
538 r"^media[\\/]gpu[\\/].*\.cc$",
539 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53540 ),
541 ),
542 (
Dave Tapuska98199b612019-07-10 13:30:44543 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20544 (
thomasanderson11aa41d2017-06-08 22:22:38545 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20546 ),
547 True,
548 (
Egor Paskoce145c42018-09-28 19:31:04549 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
550 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
551 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20552 ),
553 ),
554 (
tomhudsone2c14d552016-05-26 17:07:46555 'setMatrixClip',
556 (
557 'Overriding setMatrixClip() is prohibited; ',
558 'the base function is deprecated. ',
559 ),
560 True,
561 (),
562 ),
563 (
[email protected]52657f62013-05-20 05:30:31564 'SkRefPtr',
565 (
566 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22567 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31568 ),
569 True,
570 (),
571 ),
572 (
573 'SkAutoRef',
574 (
575 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22576 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31577 ),
578 True,
579 (),
580 ),
581 (
582 'SkAutoTUnref',
583 (
584 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22585 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31586 ),
587 True,
588 (),
589 ),
590 (
591 'SkAutoUnref',
592 (
593 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
594 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22595 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31596 ),
597 True,
598 (),
599 ),
[email protected]d89eec82013-12-03 14:10:59600 (
601 r'/HANDLE_EINTR\(.*close',
602 (
603 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
604 'descriptor will be closed, and it is incorrect to retry the close.',
605 'Either call close directly and ignore its return value, or wrap close',
606 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
607 ),
608 True,
609 (),
610 ),
611 (
612 r'/IGNORE_EINTR\((?!.*close)',
613 (
614 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
615 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
616 ),
617 True,
618 (
619 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04620 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
621 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59622 ),
623 ),
[email protected]ec5b3f02014-04-04 18:43:43624 (
625 r'/v8::Extension\(',
626 (
627 'Do not introduce new v8::Extensions into the code base, use',
628 'gin::Wrappable instead. See http://crbug.com/334679',
629 ),
630 True,
[email protected]f55c90ee62014-04-12 00:50:03631 (
Egor Paskoce145c42018-09-28 19:31:04632 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03633 ),
[email protected]ec5b3f02014-04-04 18:43:43634 ),
skyostilf9469f72015-04-20 10:38:52635 (
jame2d1a952016-04-02 00:27:10636 '#pragma comment(lib,',
637 (
638 'Specify libraries to link with in build files and not in the source.',
639 ),
640 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41641 (
tzik3f295992018-12-04 20:32:23642 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04643 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41644 ),
jame2d1a952016-04-02 00:27:10645 ),
fdorayc4ac18d2017-05-01 21:39:59646 (
Gabriel Charette7cc6c432018-04-25 20:52:02647 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59648 (
649 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
650 ),
651 False,
652 (),
653 ),
654 (
Gabriel Charette7cc6c432018-04-25 20:52:02655 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59656 (
657 'Consider using THREAD_CHECKER macros instead of the class directly.',
658 ),
659 False,
660 (),
661 ),
dbeamb6f4fde2017-06-15 04:03:06662 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06663 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
664 (
665 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
666 'deprecated (http://crbug.com/634507). Please avoid converting away',
667 'from the Time types in Chromium code, especially if any math is',
668 'being done on time values. For interfacing with platform/library',
669 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
670 'type converter methods instead. For faking TimeXXX values (for unit',
671 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
672 'other use cases, please contact base/time/OWNERS.',
673 ),
674 False,
675 (),
676 ),
677 (
dbeamb6f4fde2017-06-15 04:03:06678 'CallJavascriptFunctionUnsafe',
679 (
680 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
681 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
682 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
683 ),
684 False,
685 (
Egor Paskoce145c42018-09-28 19:31:04686 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
687 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
688 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06689 ),
690 ),
dskiba1474c2bfd62017-07-20 02:19:24691 (
692 'leveldb::DB::Open',
693 (
694 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
695 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
696 "Chrome's tracing, making their memory usage visible.",
697 ),
698 True,
699 (
700 r'^third_party/leveldatabase/.*\.(cc|h)$',
701 ),
Gabriel Charette0592c3a2017-07-26 12:02:04702 ),
703 (
Chris Mumfordc38afb62017-10-09 17:55:08704 'leveldb::NewMemEnv',
705 (
706 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58707 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
708 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08709 ),
710 True,
711 (
712 r'^third_party/leveldatabase/.*\.(cc|h)$',
713 ),
714 ),
715 (
Gabriel Charetted9839bc2017-07-29 14:17:47716 'RunLoop::QuitCurrent',
717 (
Robert Liao64b7ab22017-08-04 23:03:43718 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
719 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47720 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41721 False,
Gabriel Charetted9839bc2017-07-29 14:17:47722 (),
Gabriel Charettea44975052017-08-21 23:14:04723 ),
724 (
725 'base::ScopedMockTimeMessageLoopTaskRunner',
726 (
Gabriel Charette87cc1af2018-04-25 20:52:51727 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11728 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51729 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
730 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
731 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04732 ),
Gabriel Charette87cc1af2018-04-25 20:52:51733 False,
Gabriel Charettea44975052017-08-21 23:14:04734 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57735 ),
736 (
Dave Tapuska98199b612019-07-10 13:30:44737 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57738 (
739 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02740 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57741 ),
742 True,
743 (),
Francois Doray43670e32017-09-27 12:40:38744 ),
745 (
Peter Kasting991618a62019-06-17 22:00:09746 r'/\bstd::stoi\b',
747 (
748 'std::stoi uses exceptions to communicate results. ',
749 'Use base::StringToInt() instead.',
750 ),
751 True,
752 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
753 ),
754 (
755 r'/\bstd::stol\b',
756 (
757 'std::stol uses exceptions to communicate results. ',
758 'Use base::StringToInt() instead.',
759 ),
760 True,
761 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
762 ),
763 (
764 r'/\bstd::stoul\b',
765 (
766 'std::stoul uses exceptions to communicate results. ',
767 'Use base::StringToUint() instead.',
768 ),
769 True,
770 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
771 ),
772 (
773 r'/\bstd::stoll\b',
774 (
775 'std::stoll uses exceptions to communicate results. ',
776 'Use base::StringToInt64() instead.',
777 ),
778 True,
779 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
780 ),
781 (
782 r'/\bstd::stoull\b',
783 (
784 'std::stoull uses exceptions to communicate results. ',
785 'Use base::StringToUint64() instead.',
786 ),
787 True,
788 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
789 ),
790 (
791 r'/\bstd::stof\b',
792 (
793 'std::stof 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::stod\b',
803 (
804 'std::stod 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 (
813 r'/\bstd::stold\b',
814 (
815 'std::stold uses exceptions to communicate results. ',
816 'For locale-independent values, e.g. reading numbers from disk',
817 'profiles, use base::StringToDouble().',
818 'For user-visible values, parse using ICU.',
819 ),
820 True,
821 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
822 ),
823 (
Daniel Bratell69334cc2019-03-26 11:07:45824 r'/\bstd::to_string\b',
825 (
826 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09827 'For locale-independent strings, e.g. writing numbers to disk',
828 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45829 'For user-visible strings, use base::FormatNumber() and',
830 'the related functions in base/i18n/number_formatting.h.',
831 ),
Peter Kasting991618a62019-06-17 22:00:09832 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21833 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45834 ),
835 (
836 r'/\bstd::shared_ptr\b',
837 (
838 'std::shared_ptr should not be used. Use scoped_refptr instead.',
839 ),
840 True,
Andreas Haas63f58792019-11-07 10:56:44841 [_THIRD_PARTY_EXCEPT_BLINK,
842 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
843 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21844 ),
845 (
Peter Kasting991618a62019-06-17 22:00:09846 r'/\bstd::weak_ptr\b',
847 (
848 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
849 ),
850 True,
851 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
852 ),
853 (
Daniel Bratell609102be2019-03-27 20:53:21854 r'/\blong long\b',
855 (
856 'long long is banned. Use stdint.h if you need a 64 bit number.',
857 ),
858 False, # Only a warning since it is already used.
859 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
860 ),
861 (
862 r'/\bstd::bind\b',
863 (
864 'std::bind is banned because of lifetime risks.',
865 'Use base::BindOnce or base::BindRepeating instead.',
866 ),
867 True,
868 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
869 ),
870 (
871 r'/\b#include <chrono>\b',
872 (
873 '<chrono> overlaps with Time APIs in base. Keep using',
874 'base classes.',
875 ),
876 True,
877 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
878 ),
879 (
880 r'/\b#include <exception>\b',
881 (
882 'Exceptions are banned and disabled in Chromium.',
883 ),
884 True,
885 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
886 ),
887 (
888 r'/\bstd::function\b',
889 (
890 'std::function is banned. Instead use base::Callback which directly',
891 'supports Chromium\'s weak pointers, ref counting and more.',
892 ),
Peter Kasting991618a62019-06-17 22:00:09893 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21894 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
895 ),
896 (
897 r'/\b#include <random>\b',
898 (
899 'Do not use any random number engines from <random>. Instead',
900 'use base::RandomBitGenerator.',
901 ),
902 True,
903 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
904 ),
905 (
906 r'/\bstd::ratio\b',
907 (
908 'std::ratio is banned by the Google Style Guide.',
909 ),
910 True,
911 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45912 ),
913 (
Francois Doray43670e32017-09-27 12:40:38914 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
915 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
916 (
917 'Use the new API in base/threading/thread_restrictions.h.',
918 ),
Gabriel Charette04b138f2018-08-06 00:03:22919 False,
Francois Doray43670e32017-09-27 12:40:38920 (),
921 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38922 (
danakj7a2b7082019-05-21 21:13:51923 r'/\bbase::Bind\(',
924 (
925 'Please use base::Bind{Once,Repeating} instead',
926 'of base::Bind. (crbug.com/714018)',
927 ),
928 False,
929 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
930 ),
931 (
932 r'/\bbase::Callback[<:]',
933 (
934 'Please use base::{Once,Repeating}Callback instead',
935 'of base::Callback. (crbug.com/714018)',
936 ),
937 False,
938 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
939 ),
940 (
941 r'/\bbase::Closure\b',
942 (
943 'Please use base::{Once,Repeating}Closure instead',
944 'of base::Closure. (crbug.com/714018)',
945 ),
946 False,
947 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
948 ),
949 (
Alex Ilin5929abe32019-04-03 17:09:34950 r'/base::SharedMemory(|Handle)',
Alex Ilin63058f62019-03-28 19:29:45951 (
952 'base::SharedMemory is deprecated. Please use',
953 '{Writable,ReadOnly}SharedMemoryRegion instead.',
954 ),
955 False,
956 (),
957 ),
958 (
Michael Giuffrida7f93d6922019-04-19 14:39:58959 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19960 (
961 'RunMessageLoop is deprecated, use RunLoop instead.',
962 ),
963 False,
964 (),
965 ),
966 (
Dave Tapuska98199b612019-07-10 13:30:44967 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19968 (
969 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
970 ),
971 False,
972 (),
973 ),
974 (
Dave Tapuska98199b612019-07-10 13:30:44975 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19976 (
977 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
978 "if you're convinced you need this.",
979 ),
980 False,
981 (),
982 ),
983 (
Dave Tapuska98199b612019-07-10 13:30:44984 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19985 (
986 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04987 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19988 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
989 'async events instead of flushing threads.',
990 ),
991 False,
992 (),
993 ),
994 (
995 r'MessageLoopRunner',
996 (
997 'MessageLoopRunner is deprecated, use RunLoop instead.',
998 ),
999 False,
1000 (),
1001 ),
1002 (
Dave Tapuska98199b612019-07-10 13:30:441003 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:191004 (
1005 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
1006 "gab@ if you found a use case where this is the only solution.",
1007 ),
1008 False,
1009 (),
1010 ),
1011 (
Victor Costane48a2e82019-03-15 22:02:341012 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161013 (
Victor Costane48a2e82019-03-15 22:02:341014 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161015 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1016 ),
1017 True,
1018 (
1019 r'^sql/initialization\.(cc|h)$',
1020 r'^third_party/sqlite/.*\.(c|cc|h)$',
1021 ),
1022 ),
Matt Menke7f520a82018-03-28 21:38:371023 (
1024 'net::URLFetcher',
1025 (
1026 'net::URLFetcher should no longer be used in content embedders. ',
1027 'Instead, use network::SimpleURLLoader instead, which supports ',
1028 'an out-of-process network stack. ',
1029 'net::URLFetcher may still be used in binaries that do not embed',
1030 'content.',
1031 ),
Matt Menke59716d02018-04-05 12:45:531032 False,
Matt Menke7f520a82018-03-28 21:38:371033 (
Egor Paskoce145c42018-09-28 19:31:041034 r'^ios[\\/].*\.(cc|h)$',
1035 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:371036 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:041037 r'^net[\\/].*\.(cc|h)$',
1038 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:431039 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:371040 ),
1041 ),
jdoerried7d10ab2018-04-27 10:46:131042 (
Dave Tapuska98199b612019-07-10 13:30:441043 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471044 (
1045 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1046 'base::RandomShuffle instead.'
1047 ),
1048 True,
1049 (),
1050 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241051 (
1052 'ios/web/public/test/http_server',
1053 (
1054 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1055 ),
1056 False,
1057 (),
1058 ),
Robert Liao764c9492019-01-24 18:46:281059 (
1060 'GetAddressOf',
1061 (
1062 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:461063 'implicated in a few leaks. Use operator& instead. See ',
1064 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:281065 ),
1066 True,
1067 (),
1068 ),
Antonio Gomes07300d02019-03-13 20:59:571069 (
1070 'DEFINE_TYPE_CASTS',
1071 (
1072 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1073 '//third_party/blink/renderer/platform/casting.h.'
1074 ),
1075 True,
1076 (
1077 r'^third_party/blink/renderer/.*\.(cc|h)$',
1078 ),
1079 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381080 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:451081 r'/\bIsHTML.+Element\(\b',
1082 (
1083 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1084 ' helpers IsA<HTMLXXXXElement> from ',
1085 '//third_party/blink/renderer/platform/casting.h.'
1086 ),
1087 False,
1088 (
1089 r'^third_party/blink/renderer/.*\.(cc|h)$',
1090 ),
1091 ),
1092 (
1093 r'/\bToHTML.+Element(|OrNull)\(\b',
1094 (
1095 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1096 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1097 'and DynamicTo<HTMLXXXXElement> from ',
1098 '//third_party/blink/renderer/platform/casting.h.'
1099 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1100 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1101 ),
1102 False,
1103 (
1104 r'^third_party/blink/renderer/.*\.(cc|h)$',
1105 ),
1106 ),
1107 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371108 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381109 (
1110 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1111 ),
1112 True,
1113 (),
1114 ),
Ben Lewisa9514602019-04-29 17:53:051115 (
1116 'SHFileOperation',
1117 (
1118 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1119 'complex functions to achieve the same goals. Use IFileOperation for ',
1120 'any esoteric actions instead.'
1121 ),
1122 True,
1123 (),
1124 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181125 (
Cliff Smolinsky81951642019-04-30 21:39:511126 'StringFromGUID2',
1127 (
1128 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1129 'Use base::win::String16FromGUID instead.'
1130 ),
1131 True,
1132 (
1133 r'/base/win/win_util_unittest.cc'
1134 ),
1135 ),
1136 (
1137 'StringFromCLSID',
1138 (
1139 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1140 'Use base::win::String16FromGUID instead.'
1141 ),
1142 True,
1143 (
1144 r'/base/win/win_util_unittest.cc'
1145 ),
1146 ),
1147 (
Avi Drissman7382afa02019-04-29 23:27:131148 'kCFAllocatorNull',
1149 (
1150 'The use of kCFAllocatorNull with the NoCopy creation of ',
1151 'CoreFoundation types is prohibited.',
1152 ),
1153 True,
1154 (),
1155 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291156 (
1157 'mojo::ConvertTo',
1158 (
1159 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1160 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1161 'StringTraits if you would like to convert between custom types and',
1162 'the wire format of mojom types.'
1163 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221164 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291165 (
Wezf89dec092019-09-11 19:38:331166 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1167 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291168 r'^third_party/blink/.*\.(cc|h)$',
1169 r'^content/renderer/.*\.(cc|h)$',
1170 ),
1171 ),
Robert Liao1d78df52019-11-11 20:02:011172 (
1173 'CComPtr',
1174 (
1175 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1176 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1177 'details.'
1178 ),
1179 False,
1180 (),
1181 ),
[email protected]127f18ec2012-06-16 05:05:591182)
1183
Mario Sanchez Prada2472cab2019-09-18 10:58:311184# Format: Sequence of tuples containing:
1185# * String pattern or, if starting with a slash, a regular expression.
1186# * Sequence of strings to show when the pattern matches.
1187_DEPRECATED_MOJO_TYPES = (
1188 (
1189 r'/\bmojo::AssociatedBinding\b',
1190 (
1191 'mojo::AssociatedBinding<Interface> is deprecated.',
1192 'Use mojo::AssociatedReceiver<Interface> instead.',
1193 ),
1194 ),
1195 (
1196 r'/\bmojo::AssociatedBindingSet\b',
1197 (
1198 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1199 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1200 ),
1201 ),
1202 (
1203 r'/\bmojo::AssociatedInterfacePtr\b',
1204 (
1205 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1206 'Use mojo::AssociatedRemote<Interface> instead.',
1207 ),
1208 ),
1209 (
1210 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1211 (
1212 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1213 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1214 ),
1215 ),
1216 (
1217 r'/\bmojo::AssociatedInterfaceRequest\b',
1218 (
1219 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1220 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1221 ),
1222 ),
1223 (
1224 r'/\bmojo::Binding\b',
1225 (
1226 'mojo::Binding<Interface> is deprecated.',
1227 'Use mojo::Receiver<Interface> instead.',
1228 ),
1229 ),
1230 (
1231 r'/\bmojo::BindingSet\b',
1232 (
1233 'mojo::BindingSet<Interface> is deprecated.',
1234 'Use mojo::ReceiverSet<Interface> instead.',
1235 ),
1236 ),
1237 (
1238 r'/\bmojo::InterfacePtr\b',
1239 (
1240 'mojo::InterfacePtr<Interface> is deprecated.',
1241 'Use mojo::Remote<Interface> instead.',
1242 ),
1243 ),
1244 (
1245 r'/\bmojo::InterfacePtrInfo\b',
1246 (
1247 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1248 'Use mojo::PendingRemote<Interface> instead.',
1249 ),
1250 ),
1251 (
1252 r'/\bmojo::InterfaceRequest\b',
1253 (
1254 'mojo::InterfaceRequest<Interface> is deprecated.',
1255 'Use mojo::PendingReceiver<Interface> instead.',
1256 ),
1257 ),
1258 (
1259 r'/\bmojo::MakeRequest\b',
1260 (
1261 'mojo::MakeRequest is deprecated.',
1262 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1263 ),
1264 ),
1265 (
1266 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1267 (
1268 'mojo::MakeRequest is deprecated.',
1269 'Use mojo::AssociatedRemote::'
1270 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1271 ),
1272 ),
1273 (
1274 r'/\bmojo::MakeStrongBinding\b',
1275 (
1276 'mojo::MakeStrongBinding is deprecated.',
1277 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1278 'mojo::MakeSelfOwnedReceiver() instead.',
1279 ),
1280 ),
1281 (
1282 r'/\bmojo::MakeStrongAssociatedBinding\b',
1283 (
1284 'mojo::MakeStrongAssociatedBinding is deprecated.',
1285 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1286 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1287 ),
1288 ),
1289 (
1290 r'/\bmojo::StrongAssociatedBindingSet\b',
1291 (
1292 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1293 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1294 ),
1295 ),
1296 (
1297 r'/\bmojo::StrongBindingSet\b',
1298 (
1299 'mojo::StrongBindingSet<Interface> is deprecated.',
1300 'Use mojo::UniqueReceiverSet<Interface> instead.',
1301 ),
1302 ),
1303)
wnwenbdc444e2016-05-25 13:44:151304
mlamouria82272622014-09-16 18:45:041305_IPC_ENUM_TRAITS_DEPRECATED = (
1306 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501307 'See http://www.chromium.org/Home/chromium-security/education/'
1308 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041309
Stephen Martinis97a394142018-06-07 23:06:051310_LONG_PATH_ERROR = (
1311 'Some files included in this CL have file names that are too long (> 200'
1312 ' characters). If committed, these files will cause issues on Windows. See'
1313 ' https://crbug.com/612667 for more details.'
1314)
1315
Shenghua Zhangbfaa38b82017-11-16 21:58:021316_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041317 r".*[\\/]BuildHooksAndroidImpl\.java",
1318 r".*[\\/]LicenseContentProvider\.java",
1319 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281320 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021321]
[email protected]127f18ec2012-06-16 05:05:591322
Mohamed Heikald048240a2019-11-12 16:57:371323# List of image extensions that are used as resources in chromium.
1324_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1325
Sean Kau46e29bc2017-08-28 16:31:161326# These paths contain test data and other known invalid JSON files.
1327_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041328 r'test[\\/]data[\\/]',
1329 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1330 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041331 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431332 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161333]
1334
1335
[email protected]b00342e7f2013-03-26 16:21:541336_VALID_OS_MACROS = (
1337 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081338 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541339 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121340 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541341 'OS_BSD',
1342 'OS_CAT', # For testing.
1343 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041344 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541345 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371346 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541347 'OS_IOS',
1348 'OS_LINUX',
1349 'OS_MACOSX',
1350 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211351 'OS_NACL_NONSFI',
1352 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121353 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541354 'OS_OPENBSD',
1355 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371356 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541357 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541358 'OS_WIN',
1359)
1360
1361
agrievef32bcc72016-04-04 14:57:401362_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391363 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361364 'base/android/jni_generator/jni_generator.pydeps',
1365 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221366 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361367 'build/android/gyp/aar.pydeps',
1368 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271369 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361370 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381371 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361372 'build/android/gyp/bytecode_processor.pydeps',
1373 'build/android/gyp/compile_resources.pydeps',
Tibor Goldschwendt84ec04c2019-08-23 21:19:091374 'build/android/gyp/create_app_bundle_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361375 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1376 'build/android/gyp/copy_ex.pydeps',
1377 'build/android/gyp/create_app_bundle.pydeps',
1378 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361379 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221380 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361381 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591382 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361383 'build/android/gyp/dex.pydeps',
1384 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361385 'build/android/gyp/filter_zip.pydeps',
1386 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361387 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361388 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581389 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361390 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261391 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361392 'build/android/gyp/javac.pydeps',
1393 'build/android/gyp/jinja_template.pydeps',
1394 'build/android/gyp/lint.pydeps',
1395 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361396 'build/android/gyp/merge_manifest.pydeps',
1397 'build/android/gyp/prepare_resources.pydeps',
1398 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241399 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361400 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461401 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561402 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361403 'build/android/incremental_install/generate_android_manifest.pydeps',
1404 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221405 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401406 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041407 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361408 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411409 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051410 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191411 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431412 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021413 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401414]
1415
wnwenbdc444e2016-05-25 13:44:151416
agrievef32bcc72016-04-04 14:57:401417_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421418 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131419 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421420 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1421 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131422 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
John Budorickbc3571aa2019-04-25 02:20:061423 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221424 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401425]
1426
wnwenbdc444e2016-05-25 13:44:151427
agrievef32bcc72016-04-04 14:57:401428_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1429
1430
Eric Boren6fd2b932018-01-25 15:05:081431# Bypass the AUTHORS check for these accounts.
1432_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291433 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1434 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081435 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321436 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591437 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451438 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591439 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221440 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041441 ) | set('%[email protected]' % s
1442 for s in ('chromium-autoroll',)
1443 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301444 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081445
1446
Daniel Bratell65b033262019-04-23 08:17:061447def _IsCPlusPlusFile(input_api, file_path):
1448 """Returns True if this file contains C++-like code (and not Python,
1449 Go, Java, MarkDown, ...)"""
1450
1451 ext = input_api.os_path.splitext(file_path)[1]
1452 # This list is compatible with CppChecker.IsCppFile but we should
1453 # consider adding ".c" to it. If we do that we can use this function
1454 # at more places in the code.
1455 return ext in (
1456 '.h',
1457 '.cc',
1458 '.cpp',
1459 '.m',
1460 '.mm',
1461 )
1462
1463def _IsCPlusPlusHeaderFile(input_api, file_path):
1464 return input_api.os_path.splitext(file_path)[1] == ".h"
1465
1466
1467def _IsJavaFile(input_api, file_path):
1468 return input_api.os_path.splitext(file_path)[1] == ".java"
1469
1470
1471def _IsProtoFile(input_api, file_path):
1472 return input_api.os_path.splitext(file_path)[1] == ".proto"
1473
[email protected]55459852011-08-10 15:17:191474def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1475 """Attempts to prevent use of functions intended only for testing in
1476 non-testing code. For now this is just a best-effort implementation
1477 that ignores header files and may have some false positives. A
1478 better implementation would probably need a proper C++ parser.
1479 """
1480 # We only scan .cc files and the like, as the declaration of
1481 # for-testing functions in header files are hard to distinguish from
1482 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491483 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191484
jochenc0d4808c2015-07-27 09:25:421485 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191486 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091487 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191488 exclusion_pattern = input_api.re.compile(
1489 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1490 base_function_pattern, base_function_pattern))
1491
1492 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441493 black_list = (_EXCLUDED_PATHS +
1494 _TEST_CODE_EXCLUDED_PATHS +
1495 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191496 return input_api.FilterSourceFile(
1497 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491498 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191499 black_list=black_list)
1500
1501 problems = []
1502 for f in input_api.AffectedSourceFiles(FilterFile):
1503 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241504 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031505 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461506 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031507 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191508 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031509 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191510
1511 if problems:
[email protected]f7051d52013-04-02 18:31:421512 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031513 else:
1514 return []
[email protected]55459852011-08-10 15:17:191515
1516
Vaclav Brozek7dbc28c2018-03-27 08:35:231517def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1518 """This is a simplified version of
1519 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1520 """
1521 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1522 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1523 name_pattern = r'ForTest(s|ing)?'
1524 # Describes an occurrence of "ForTest*" inside a // comment.
1525 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1526 # Catch calls.
1527 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1528 # Ignore definitions. (Comments are ignored separately.)
1529 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1530
1531 problems = []
1532 sources = lambda x: input_api.FilterSourceFile(
1533 x,
1534 black_list=(('(?i).*test', r'.*\/junit\/')
1535 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491536 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231537 )
1538 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1539 local_path = f.LocalPath()
1540 is_inside_javadoc = False
1541 for line_number, line in f.ChangedContents():
1542 if is_inside_javadoc and javadoc_end_re.search(line):
1543 is_inside_javadoc = False
1544 if not is_inside_javadoc and javadoc_start_re.search(line):
1545 is_inside_javadoc = True
1546 if is_inside_javadoc:
1547 continue
1548 if (inclusion_re.search(line) and
1549 not comment_re.search(line) and
1550 not exclusion_re.search(line)):
1551 problems.append(
1552 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1553
1554 if problems:
1555 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1556 else:
1557 return []
1558
1559
[email protected]10689ca2011-09-02 02:31:541560def _CheckNoIOStreamInHeaders(input_api, output_api):
1561 """Checks to make sure no .h files include <iostream>."""
1562 files = []
1563 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1564 input_api.re.MULTILINE)
1565 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1566 if not f.LocalPath().endswith('.h'):
1567 continue
1568 contents = input_api.ReadFile(f)
1569 if pattern.search(contents):
1570 files.append(f)
1571
1572 if len(files):
yolandyandaabc6d2016-04-18 18:29:391573 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061574 'Do not #include <iostream> in header files, since it inserts static '
1575 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541576 '#include <ostream>. See http://crbug.com/94794',
1577 files) ]
1578 return []
1579
Danil Chapovalov3518f362018-08-11 16:13:431580def _CheckNoStrCatRedefines(input_api, output_api):
1581 """Checks no windows headers with StrCat redefined are included directly."""
1582 files = []
1583 pattern_deny = input_api.re.compile(
1584 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1585 input_api.re.MULTILINE)
1586 pattern_allow = input_api.re.compile(
1587 r'^#include\s"base/win/windows_defines.inc"',
1588 input_api.re.MULTILINE)
1589 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1590 contents = input_api.ReadFile(f)
1591 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1592 files.append(f.LocalPath())
1593
1594 if len(files):
1595 return [output_api.PresubmitError(
1596 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1597 'directly since they pollute code with StrCat macro. Instead, '
1598 'include matching header from base/win. See http://crbug.com/856536',
1599 files) ]
1600 return []
1601
[email protected]10689ca2011-09-02 02:31:541602
[email protected]72df4e782012-06-21 16:28:181603def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521604 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181605 problems = []
1606 for f in input_api.AffectedFiles():
1607 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1608 continue
1609
1610 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041611 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181612 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1613
1614 if not problems:
1615 return []
1616 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1617 '\n'.join(problems))]
1618
Dominic Battre033531052018-09-24 15:45:341619def _CheckNoDISABLETypoInTests(input_api, output_api):
1620 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1621
1622 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1623 instead of DISABLED_. To filter false positives, reports are only generated
1624 if a corresponding MAYBE_ line exists.
1625 """
1626 problems = []
1627
1628 # The following two patterns are looked for in tandem - is a test labeled
1629 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1630 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1631 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1632
1633 # This is for the case that a test is disabled on all platforms.
1634 full_disable_pattern = input_api.re.compile(
1635 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1636 input_api.re.MULTILINE)
1637
Katie Df13948e2018-09-25 07:33:441638 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341639 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1640 continue
1641
1642 # Search for MABYE_, DISABLE_ pairs.
1643 disable_lines = {} # Maps of test name to line number.
1644 maybe_lines = {}
1645 for line_num, line in f.ChangedContents():
1646 disable_match = disable_pattern.search(line)
1647 if disable_match:
1648 disable_lines[disable_match.group(1)] = line_num
1649 maybe_match = maybe_pattern.search(line)
1650 if maybe_match:
1651 maybe_lines[maybe_match.group(1)] = line_num
1652
1653 # Search for DISABLE_ occurrences within a TEST() macro.
1654 disable_tests = set(disable_lines.keys())
1655 maybe_tests = set(maybe_lines.keys())
1656 for test in disable_tests.intersection(maybe_tests):
1657 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1658
1659 contents = input_api.ReadFile(f)
1660 full_disable_match = full_disable_pattern.search(contents)
1661 if full_disable_match:
1662 problems.append(' %s' % f.LocalPath())
1663
1664 if not problems:
1665 return []
1666 return [
1667 output_api.PresubmitPromptWarning(
1668 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1669 '\n'.join(problems))
1670 ]
1671
[email protected]72df4e782012-06-21 16:28:181672
danakj61c1aa22015-10-26 19:55:521673def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571674 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521675 errors = []
1676 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1677 input_api.re.MULTILINE)
1678 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1679 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1680 continue
1681 for lnum, line in f.ChangedContents():
1682 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171683 errors.append(output_api.PresubmitError(
1684 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571685 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171686 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521687 return errors
1688
1689
Makoto Shimazu3ad422cd2019-05-08 02:35:141690def _FindHistogramNameInChunk(histogram_name, chunk):
1691 """Tries to find a histogram name or prefix in a line.
1692
1693 Returns the existence of the histogram name, or None if it needs more chunk
1694 to determine."""
mcasasb7440c282015-02-04 14:52:191695 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1696 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141697 if '<affected-histogram' in chunk:
1698 # If the tag is not completed, needs more chunk to get the name.
1699 if not '>' in chunk:
1700 return None
1701 if not 'name="' in chunk:
1702 return False
1703 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1704 # expect the only attribute is the name.
1705 histogram_prefix = chunk.split('"')[1]
1706 return histogram_prefix in histogram_name
1707 # Typically the whole histogram name should in the line.
1708 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191709
1710
1711def _CheckUmaHistogramChanges(input_api, output_api):
1712 """Check that UMA histogram names in touched lines can still be found in other
1713 lines of the patch or in histograms.xml. Note that this check would not catch
1714 the reverse: changes in histograms.xml not matched in the code itself."""
1715 touched_histograms = []
1716 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471717 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1718 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1719 name_pattern = r'"(.*?)"'
1720 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1721 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1722 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1723 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1724 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171725 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191726 for f in input_api.AffectedFiles():
1727 # If histograms.xml itself is modified, keep the modified lines for later.
1728 if f.LocalPath().endswith(('histograms.xml')):
1729 histograms_xml_modifications = f.ChangedContents()
1730 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471731 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1732 single_line_re = single_line_c_re
1733 split_line_prefix_re = split_line_c_prefix_re
1734 elif f.LocalPath().endswith(('java')):
1735 single_line_re = single_line_java_re
1736 split_line_prefix_re = split_line_java_prefix_re
1737 else:
mcasasb7440c282015-02-04 14:52:191738 continue
1739 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171740 if last_line_matched_prefix:
1741 suffix_found = split_line_suffix_re.search(line)
1742 if suffix_found :
1743 touched_histograms.append([suffix_found.group(1), f, line_num])
1744 last_line_matched_prefix = False
1745 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061746 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191747 if found:
1748 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171749 continue
1750 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191751
1752 # Search for the touched histogram names in the local modifications to
1753 # histograms.xml, and, if not found, on the base histograms.xml file.
1754 unmatched_histograms = []
1755 for histogram_info in touched_histograms:
1756 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141757 chunk = ''
mcasasb7440c282015-02-04 14:52:191758 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141759 chunk += line
1760 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1761 if histogram_name_found is None:
1762 continue
1763 chunk = ''
mcasasb7440c282015-02-04 14:52:191764 if histogram_name_found:
1765 break
1766 if not histogram_name_found:
1767 unmatched_histograms.append(histogram_info)
1768
eromanb90c82e7e32015-04-01 15:13:491769 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191770 problems = []
1771 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491772 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191773 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451774 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191775 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141776 chunk = ''
mcasasb7440c282015-02-04 14:52:191777 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141778 chunk += line
1779 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1780 chunk)
1781 if histogram_name_found is None:
1782 continue
1783 chunk = ''
mcasasb7440c282015-02-04 14:52:191784 if histogram_name_found:
1785 break
1786 if not histogram_name_found:
1787 problems.append(' [%s:%d] %s' %
1788 (f.LocalPath(), line_num, histogram_name))
1789
1790 if not problems:
1791 return []
1792 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1793 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491794 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191795
wnwenbdc444e2016-05-25 13:44:151796
yolandyandaabc6d2016-04-18 18:29:391797def _CheckFlakyTestUsage(input_api, output_api):
1798 """Check that FlakyTest annotation is our own instead of the android one"""
1799 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1800 files = []
1801 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1802 if f.LocalPath().endswith('Test.java'):
1803 if pattern.search(input_api.ReadFile(f)):
1804 files.append(f)
1805 if len(files):
1806 return [output_api.PresubmitError(
1807 'Use org.chromium.base.test.util.FlakyTest instead of '
1808 'android.test.FlakyTest',
1809 files)]
1810 return []
mcasasb7440c282015-02-04 14:52:191811
wnwenbdc444e2016-05-25 13:44:151812
[email protected]8ea5d4b2011-09-13 21:49:221813def _CheckNoNewWStrings(input_api, output_api):
1814 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271815 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221816 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201817 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571818 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341819 '/win/' in f.LocalPath() or
1820 'chrome_elf' in f.LocalPath() or
1821 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201822 continue
[email protected]8ea5d4b2011-09-13 21:49:221823
[email protected]a11dbe9b2012-08-07 01:32:581824 allowWString = False
[email protected]b5c24292011-11-28 14:38:201825 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581826 if 'presubmit: allow wstring' in line:
1827 allowWString = True
1828 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271829 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581830 allowWString = False
1831 else:
1832 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221833
[email protected]55463aa62011-10-12 00:48:271834 if not problems:
1835 return []
1836 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581837 ' If you are calling a cross-platform API that accepts a wstring, '
1838 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271839 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221840
1841
[email protected]2a8ac9c2011-10-19 17:20:441842def _CheckNoDEPSGIT(input_api, output_api):
1843 """Make sure .DEPS.git is never modified manually."""
1844 if any(f.LocalPath().endswith('.DEPS.git') for f in
1845 input_api.AffectedFiles()):
1846 return [output_api.PresubmitError(
1847 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1848 'automated system based on what\'s in DEPS and your changes will be\n'
1849 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501850 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1851 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441852 'for more information')]
1853 return []
1854
1855
tandriief664692014-09-23 14:51:471856def _CheckValidHostsInDEPS(input_api, output_api):
1857 """Checks that DEPS file deps are from allowed_hosts."""
1858 # Run only if DEPS file has been modified to annoy fewer bystanders.
1859 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1860 return []
1861 # Outsource work to gclient verify
1862 try:
John Budorickf20c0042019-04-25 23:23:401863 gclient_path = input_api.os_path.join(
1864 input_api.PresubmitLocalPath(),
1865 'third_party', 'depot_tools', 'gclient.py')
1866 input_api.subprocess.check_output(
1867 [input_api.python_executable, gclient_path, 'verify'],
1868 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471869 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201870 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471871 return [output_api.PresubmitError(
1872 'DEPS file must have only git dependencies.',
1873 long_text=error.output)]
1874
1875
Mario Sanchez Prada2472cab2019-09-18 10:58:311876def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1877 type_name, message):
1878 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1879
1880 Returns an string composed of the name of the file, the line number where the
1881 match has been found and the additional text passed as |message| in case the
1882 target type name matches the text inside the line passed as parameter.
1883 """
1884 matched = False
1885 if type_name[0:1] == '/':
1886 regex = type_name[1:]
1887 if input_api.re.search(regex, line):
1888 matched = True
1889 elif type_name in line:
1890 matched = True
1891
1892 result = []
1893 if matched:
1894 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1895 for message_line in message:
1896 result.append(' %s' % message_line)
1897
1898 return result
1899
1900
[email protected]127f18ec2012-06-16 05:05:591901def _CheckNoBannedFunctions(input_api, output_api):
1902 """Make sure that banned functions are not used."""
1903 warnings = []
1904 errors = []
1905
wnwenbdc444e2016-05-25 13:44:151906 def IsBlacklisted(affected_file, blacklist):
1907 local_path = affected_file.LocalPath()
1908 for item in blacklist:
1909 if input_api.re.match(item, local_path):
1910 return True
1911 return False
1912
Peter K. Lee6c03ccff2019-07-15 14:40:051913 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541914 local_path = affected_file.LocalPath()
1915 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1916 return False
1917 basename = input_api.os_path.basename(local_path)
1918 if 'ios' in basename.split('_'):
1919 return True
1920 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1921 if sep and 'ios' in local_path.split(sep):
1922 return True
1923 return False
1924
wnwenbdc444e2016-05-25 13:44:151925 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311926 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1927 func_name, message)
1928 if problems:
wnwenbdc444e2016-05-25 13:44:151929 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311930 errors.extend(problems)
1931 else:
1932 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151933
Eric Stevensona9a980972017-09-23 00:04:411934 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1935 for f in input_api.AffectedFiles(file_filter=file_filter):
1936 for line_num, line in f.ChangedContents():
1937 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1938 CheckForMatch(f, line_num, line, func_name, message, error)
1939
[email protected]127f18ec2012-06-16 05:05:591940 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1941 for f in input_api.AffectedFiles(file_filter=file_filter):
1942 for line_num, line in f.ChangedContents():
1943 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151944 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591945
Peter K. Lee6c03ccff2019-07-15 14:40:051946 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541947 for line_num, line in f.ChangedContents():
1948 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1949 CheckForMatch(f, line_num, line, func_name, message, error)
1950
Peter K. Lee6c03ccff2019-07-15 14:40:051951 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1952 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1953 for line_num, line in f.ChangedContents():
1954 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1955 CheckForMatch(f, line_num, line, func_name, message, error)
1956
[email protected]127f18ec2012-06-16 05:05:591957 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1958 for f in input_api.AffectedFiles(file_filter=file_filter):
1959 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491960 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491961 if IsBlacklisted(f, excluded_paths):
1962 continue
wnwenbdc444e2016-05-25 13:44:151963 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591964
1965 result = []
1966 if (warnings):
1967 result.append(output_api.PresubmitPromptWarning(
1968 'Banned functions were used.\n' + '\n'.join(warnings)))
1969 if (errors):
1970 result.append(output_api.PresubmitError(
1971 'Banned functions were used.\n' + '\n'.join(errors)))
1972 return result
1973
1974
Mario Sanchez Prada2472cab2019-09-18 10:58:311975def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1976 """Make sure that old Mojo types are not used."""
1977 warnings = []
1978
1979 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1980 for f in input_api.AffectedFiles(file_filter=file_filter):
1981 # Only need to check Blink for warnings for now.
1982 if not f.LocalPath().startswith('third_party/blink'):
1983 continue
1984
1985 for line_num, line in f.ChangedContents():
1986 for func_name, message in _DEPRECATED_MOJO_TYPES:
1987 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1988 func_name, message)
1989 if problems:
1990 warnings.extend(problems)
1991
1992 result = []
1993 if (warnings):
1994 result.append(output_api.PresubmitPromptWarning(
1995 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
1996 return result
1997
1998
[email protected]6c063c62012-07-11 19:11:061999def _CheckNoPragmaOnce(input_api, output_api):
2000 """Make sure that banned functions are not used."""
2001 files = []
2002 pattern = input_api.re.compile(r'^#pragma\s+once',
2003 input_api.re.MULTILINE)
2004 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
2005 if not f.LocalPath().endswith('.h'):
2006 continue
2007 contents = input_api.ReadFile(f)
2008 if pattern.search(contents):
2009 files.append(f)
2010
2011 if files:
2012 return [output_api.PresubmitError(
2013 'Do not use #pragma once in header files.\n'
2014 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
2015 files)]
2016 return []
2017
[email protected]127f18ec2012-06-16 05:05:592018
[email protected]e7479052012-09-19 00:26:122019def _CheckNoTrinaryTrueFalse(input_api, output_api):
2020 """Checks to make sure we don't introduce use of foo ? true : false."""
2021 problems = []
2022 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2023 for f in input_api.AffectedFiles():
2024 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2025 continue
2026
2027 for line_num, line in f.ChangedContents():
2028 if pattern.match(line):
2029 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2030
2031 if not problems:
2032 return []
2033 return [output_api.PresubmitPromptWarning(
2034 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2035 '\n'.join(problems))]
2036
2037
[email protected]55f9f382012-07-31 11:02:182038def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282039 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182040 change. Breaking - rules is an error, breaking ! rules is a
2041 warning.
2042 """
mohan.reddyf21db962014-10-16 12:26:472043 import sys
[email protected]55f9f382012-07-31 11:02:182044 # We need to wait until we have an input_api object and use this
2045 # roundabout construct to import checkdeps because this file is
2046 # eval-ed and thus doesn't have __file__.
2047 original_sys_path = sys.path
2048 try:
2049 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472050 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182051 import checkdeps
[email protected]55f9f382012-07-31 11:02:182052 from rules import Rule
2053 finally:
2054 # Restore sys.path to what it was before.
2055 sys.path = original_sys_path
2056
2057 added_includes = []
rhalavati08acd232017-04-03 07:23:282058 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242059 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182060 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062061 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502062 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082063 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062064 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502065 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082066 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062067 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502068 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082069 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182070
[email protected]26385172013-05-09 23:11:352071 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182072
2073 error_descriptions = []
2074 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282075 error_subjects = set()
2076 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182077 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2078 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082079 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182080 description_with_path = '%s\n %s' % (path, rule_description)
2081 if rule_type == Rule.DISALLOW:
2082 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282083 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182084 else:
2085 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282086 warning_subjects.add("#includes")
2087
2088 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2089 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082090 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282091 description_with_path = '%s\n %s' % (path, rule_description)
2092 if rule_type == Rule.DISALLOW:
2093 error_descriptions.append(description_with_path)
2094 error_subjects.add("imports")
2095 else:
2096 warning_descriptions.append(description_with_path)
2097 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182098
Jinsuk Kim5a092672017-10-24 22:42:242099 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022100 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082101 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242102 description_with_path = '%s\n %s' % (path, rule_description)
2103 if rule_type == Rule.DISALLOW:
2104 error_descriptions.append(description_with_path)
2105 error_subjects.add("imports")
2106 else:
2107 warning_descriptions.append(description_with_path)
2108 warning_subjects.add("imports")
2109
[email protected]55f9f382012-07-31 11:02:182110 results = []
2111 if error_descriptions:
2112 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282113 'You added one or more %s that violate checkdeps rules.'
2114 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182115 error_descriptions))
2116 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422117 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282118 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182119 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282120 '%s? See relevant DEPS file(s) for details and contacts.' %
2121 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182122 warning_descriptions))
2123 return results
2124
2125
[email protected]fbcafe5a2012-08-08 15:31:222126def _CheckFilePermissions(input_api, output_api):
2127 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152128 if input_api.platform == 'win32':
2129 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292130 checkperms_tool = input_api.os_path.join(
2131 input_api.PresubmitLocalPath(),
2132 'tools', 'checkperms', 'checkperms.py')
2133 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472134 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392135 with input_api.CreateTemporaryFile() as file_list:
2136 for f in input_api.AffectedFiles():
2137 # checkperms.py file/directory arguments must be relative to the
2138 # repository.
2139 file_list.write(f.LocalPath() + '\n')
2140 file_list.close()
2141 args += ['--file-list', file_list.name]
2142 try:
2143 input_api.subprocess.check_output(args)
2144 return []
2145 except input_api.subprocess.CalledProcessError as error:
2146 return [output_api.PresubmitError(
2147 'checkperms.py failed:',
2148 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222149
2150
robertocn832f5992017-01-04 19:01:302151def _CheckTeamTags(input_api, output_api):
2152 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2153 checkteamtags_tool = input_api.os_path.join(
2154 input_api.PresubmitLocalPath(),
2155 'tools', 'checkteamtags', 'checkteamtags.py')
2156 args = [input_api.python_executable, checkteamtags_tool,
2157 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222158 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302159 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2160 'OWNERS']
2161 try:
2162 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052163 warnings = input_api.subprocess.check_output(args + files).splitlines()
2164 if warnings:
2165 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302166 return []
2167 except input_api.subprocess.CalledProcessError as error:
2168 return [output_api.PresubmitError(
2169 'checkteamtags.py failed:',
2170 long_text=error.output)]
2171
2172
[email protected]c8278b32012-10-30 20:35:492173def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2174 """Makes sure we don't include ui/aura/window_property.h
2175 in header files.
2176 """
2177 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2178 errors = []
2179 for f in input_api.AffectedFiles():
2180 if not f.LocalPath().endswith('.h'):
2181 continue
2182 for line_num, line in f.ChangedContents():
2183 if pattern.match(line):
2184 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2185
2186 results = []
2187 if errors:
2188 results.append(output_api.PresubmitError(
2189 'Header files should not include ui/aura/window_property.h', errors))
2190 return results
2191
2192
[email protected]70ca77752012-11-20 03:45:032193def _CheckForVersionControlConflictsInFile(input_api, f):
2194 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2195 errors = []
2196 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162197 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232198 # First-level headers in markdown look a lot like version control
2199 # conflict markers. http://daringfireball.net/projects/markdown/basics
2200 continue
[email protected]70ca77752012-11-20 03:45:032201 if pattern.match(line):
2202 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2203 return errors
2204
2205
2206def _CheckForVersionControlConflicts(input_api, output_api):
2207 """Usually this is not intentional and will cause a compile failure."""
2208 errors = []
2209 for f in input_api.AffectedFiles():
2210 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2211
2212 results = []
2213 if errors:
2214 results.append(output_api.PresubmitError(
2215 'Version control conflict markers found, please resolve.', errors))
2216 return results
2217
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202218
estadee17314a02017-01-12 16:22:162219def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2220 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2221 errors = []
2222 for f in input_api.AffectedFiles():
2223 for line_num, line in f.ChangedContents():
2224 if pattern.search(line):
2225 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2226
2227 results = []
2228 if errors:
2229 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502230 'Found Google support URL addressed by answer number. Please replace '
2231 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162232 return results
2233
[email protected]70ca77752012-11-20 03:45:032234
[email protected]06e6d0ff2012-12-11 01:36:442235def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2236 def FilterFile(affected_file):
2237 """Filter function for use with input_api.AffectedSourceFiles,
2238 below. This filters out everything except non-test files from
2239 top-level directories that generally speaking should not hard-code
2240 service URLs (e.g. src/android_webview/, src/content/ and others).
2241 """
2242 return input_api.FilterSourceFile(
2243 affected_file,
Egor Paskoce145c42018-09-28 19:31:042244 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442245 black_list=(_EXCLUDED_PATHS +
2246 _TEST_CODE_EXCLUDED_PATHS +
2247 input_api.DEFAULT_BLACK_LIST))
2248
reillyi38965732015-11-16 18:27:332249 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2250 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462251 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2252 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442253 problems = [] # items are (filename, line_number, line)
2254 for f in input_api.AffectedSourceFiles(FilterFile):
2255 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462256 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442257 problems.append((f.LocalPath(), line_num, line))
2258
2259 if problems:
[email protected]f7051d52013-04-02 18:31:422260 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442261 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582262 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442263 [' %s:%d: %s' % (
2264 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032265 else:
2266 return []
[email protected]06e6d0ff2012-12-11 01:36:442267
2268
James Cook6b6597c2019-11-06 22:05:292269def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2270 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2271 def FileFilter(affected_file):
2272 """Includes directories known to be Chrome OS only."""
2273 return input_api.FilterSourceFile(
2274 affected_file,
2275 white_list=('^ash/',
2276 '^chromeos/', # Top-level src/chromeos.
2277 '/chromeos/', # Any path component.
2278 '^components/arc',
2279 '^components/exo'),
2280 black_list=(input_api.DEFAULT_BLACK_LIST))
2281
2282 prefs = []
2283 priority_prefs = []
2284 for f in input_api.AffectedFiles(file_filter=FileFilter):
2285 for line_num, line in f.ChangedContents():
2286 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2287 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2288 prefs.append(' %s' % line)
2289 if input_api.re.search(
2290 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2291 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2292 priority_prefs.append(' %s' % line)
2293
2294 results = []
2295 if (prefs):
2296 results.append(output_api.PresubmitPromptWarning(
2297 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2298 'by browser sync settings. If these prefs should be controlled by OS '
2299 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2300 if (priority_prefs):
2301 results.append(output_api.PresubmitPromptWarning(
2302 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2303 'controlled by browser sync settings. If these prefs should be '
2304 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2305 'instead.\n' + '\n'.join(prefs)))
2306 return results
2307
2308
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492309# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272310def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2311 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312312 The native_client_sdk directory is excluded because it has auto-generated PNG
2313 files for documentation.
[email protected]d2530012013-01-25 16:39:272314 """
[email protected]d2530012013-01-25 16:39:272315 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492316 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042317 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312318 file_filter = lambda f: input_api.FilterSourceFile(
2319 f, white_list=white_list, black_list=black_list)
2320 for f in input_api.AffectedFiles(include_deletes=False,
2321 file_filter=file_filter):
2322 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272323
2324 results = []
2325 if errors:
2326 results.append(output_api.PresubmitError(
2327 'The name of PNG files should not have abbreviations. \n'
2328 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2329 'Contact [email protected] if you have questions.', errors))
2330 return results
2331
2332
Daniel Cheng4dcdb6b2017-04-13 08:30:172333def _ExtractAddRulesFromParsedDeps(parsed_deps):
2334 """Extract the rules that add dependencies from a parsed DEPS file.
2335
2336 Args:
2337 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2338 add_rules = set()
2339 add_rules.update([
2340 rule[1:] for rule in parsed_deps.get('include_rules', [])
2341 if rule.startswith('+') or rule.startswith('!')
2342 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502343 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172344 {}).iteritems():
2345 add_rules.update([
2346 rule[1:] for rule in rules
2347 if rule.startswith('+') or rule.startswith('!')
2348 ])
2349 return add_rules
2350
2351
2352def _ParseDeps(contents):
2353 """Simple helper for parsing DEPS files."""
2354 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172355 class _VarImpl:
2356
2357 def __init__(self, local_scope):
2358 self._local_scope = local_scope
2359
2360 def Lookup(self, var_name):
2361 """Implements the Var syntax."""
2362 try:
2363 return self._local_scope['vars'][var_name]
2364 except KeyError:
2365 raise Exception('Var is not defined: %s' % var_name)
2366
2367 local_scope = {}
2368 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172369 'Var': _VarImpl(local_scope).Lookup,
2370 }
2371 exec contents in global_scope, local_scope
2372 return local_scope
2373
2374
2375def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082376 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412377 a set of DEPS entries that we should look up.
2378
2379 For a directory (rather than a specific filename) we fake a path to
2380 a specific filename by adding /DEPS. This is chosen as a file that
2381 will seldom or never be subject to per-file include_rules.
2382 """
[email protected]2b438d62013-11-14 17:54:142383 # We ignore deps entries on auto-generated directories.
2384 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082385
Daniel Cheng4dcdb6b2017-04-13 08:30:172386 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2387 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2388
2389 added_deps = new_deps.difference(old_deps)
2390
[email protected]2b438d62013-11-14 17:54:142391 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172392 for added_dep in added_deps:
2393 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2394 continue
2395 # Assume that a rule that ends in .h is a rule for a specific file.
2396 if added_dep.endswith('.h'):
2397 results.add(added_dep)
2398 else:
2399 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082400 return results
2401
2402
[email protected]e871964c2013-05-13 14:14:552403def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2404 """When a dependency prefixed with + is added to a DEPS file, we
2405 want to make sure that the change is reviewed by an OWNER of the
2406 target file or directory, to avoid layering violations from being
2407 introduced. This check verifies that this happens.
2408 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172409 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242410
2411 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492412 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242413 for f in input_api.AffectedFiles(include_deletes=False,
2414 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552415 filename = input_api.os_path.basename(f.LocalPath())
2416 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172417 virtual_depended_on_files.update(_CalculateAddedDeps(
2418 input_api.os_path,
2419 '\n'.join(f.OldContents()),
2420 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552421
[email protected]e871964c2013-05-13 14:14:552422 if not virtual_depended_on_files:
2423 return []
2424
2425 if input_api.is_committing:
2426 if input_api.tbr:
2427 return [output_api.PresubmitNotifyResult(
2428 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272429 if input_api.dry_run:
2430 return [output_api.PresubmitNotifyResult(
2431 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552432 if not input_api.change.issue:
2433 return [output_api.PresubmitError(
2434 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402435 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552436 output = output_api.PresubmitError
2437 else:
2438 output = output_api.PresubmitNotifyResult
2439
2440 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502441 owner_email, reviewers = (
2442 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2443 input_api,
2444 owners_db.email_regexp,
2445 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552446
2447 owner_email = owner_email or input_api.change.author_email
2448
[email protected]de4f7d22013-05-23 14:27:462449 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512450 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462451 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552452 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2453 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412454
2455 # We strip the /DEPS part that was added by
2456 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2457 # directory.
2458 def StripDeps(path):
2459 start_deps = path.rfind('/DEPS')
2460 if start_deps != -1:
2461 return path[:start_deps]
2462 else:
2463 return path
2464 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552465 for path in missing_files]
2466
2467 if unapproved_dependencies:
2468 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152469 output('You need LGTM from owners of depends-on paths in DEPS that were '
2470 'modified in this CL:\n %s' %
2471 '\n '.join(sorted(unapproved_dependencies)))]
2472 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2473 output_list.append(output(
2474 'Suggested missing target path OWNERS:\n %s' %
2475 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552476 return output_list
2477
2478 return []
2479
2480
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492481# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402482def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492483 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402484 black_list = (_EXCLUDED_PATHS +
2485 _TEST_CODE_EXCLUDED_PATHS +
2486 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042487 (r"^base[\\/]logging\.h$",
2488 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222489 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042490 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2491 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2492 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122493 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182494 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152495 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032496 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152497 r"^chrome[\\/]chrome_cleaner[\\/].*",
2498 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2499 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042500 r"^chromecast[\\/]",
2501 r"^cloud_print[\\/]",
2502 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482503 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042504 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312505 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042506 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462507 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042508 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462509 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042510 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252511 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042512 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2513 r"^courgette[\\/]courgette_tool\.cc$",
2514 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272515 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002516 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332517 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042518 r"^ipc[\\/]ipc_logging\.cc$",
2519 r"^native_client_sdk[\\/]",
2520 r"^remoting[\\/]base[\\/]logging\.h$",
2521 r"^remoting[\\/]host[\\/].*",
2522 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062523 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332524 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042525 r"^tools[\\/]",
2526 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2527 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332528 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402529 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492530 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402531
thomasanderson625d3932017-03-29 07:16:582532 log_info = set([])
2533 printf = set([])
[email protected]85218562013-11-22 07:41:402534
2535 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582536 for _, line in f.ChangedContents():
2537 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2538 log_info.add(f.LocalPath())
2539 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2540 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372541
thomasanderson625d3932017-03-29 07:16:582542 if input_api.re.search(r"\bprintf\(", line):
2543 printf.add(f.LocalPath())
2544 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2545 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402546
2547 if log_info:
2548 return [output_api.PresubmitError(
2549 'These files spam the console log with LOG(INFO):',
2550 items=log_info)]
2551 if printf:
2552 return [output_api.PresubmitError(
2553 'These files spam the console log with printf/fprintf:',
2554 items=printf)]
2555 return []
2556
2557
[email protected]49aa76a2013-12-04 06:59:162558def _CheckForAnonymousVariables(input_api, output_api):
2559 """These types are all expected to hold locks while in scope and
2560 so should never be anonymous (which causes them to be immediately
2561 destroyed)."""
2562 they_who_must_be_named = [
2563 'base::AutoLock',
2564 'base::AutoReset',
2565 'base::AutoUnlock',
2566 'SkAutoAlphaRestore',
2567 'SkAutoBitmapShaderInstall',
2568 'SkAutoBlitterChoose',
2569 'SkAutoBounderCommit',
2570 'SkAutoCallProc',
2571 'SkAutoCanvasRestore',
2572 'SkAutoCommentBlock',
2573 'SkAutoDescriptor',
2574 'SkAutoDisableDirectionCheck',
2575 'SkAutoDisableOvalCheck',
2576 'SkAutoFree',
2577 'SkAutoGlyphCache',
2578 'SkAutoHDC',
2579 'SkAutoLockColors',
2580 'SkAutoLockPixels',
2581 'SkAutoMalloc',
2582 'SkAutoMaskFreeImage',
2583 'SkAutoMutexAcquire',
2584 'SkAutoPathBoundsUpdate',
2585 'SkAutoPDFRelease',
2586 'SkAutoRasterClipValidate',
2587 'SkAutoRef',
2588 'SkAutoTime',
2589 'SkAutoTrace',
2590 'SkAutoUnref',
2591 ]
2592 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2593 # bad: base::AutoLock(lock.get());
2594 # not bad: base::AutoLock lock(lock.get());
2595 bad_pattern = input_api.re.compile(anonymous)
2596 # good: new base::AutoLock(lock.get())
2597 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2598 errors = []
2599
2600 for f in input_api.AffectedFiles():
2601 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2602 continue
2603 for linenum, line in f.ChangedContents():
2604 if bad_pattern.search(line) and not good_pattern.search(line):
2605 errors.append('%s:%d' % (f.LocalPath(), linenum))
2606
2607 if errors:
2608 return [output_api.PresubmitError(
2609 'These lines create anonymous variables that need to be named:',
2610 items=errors)]
2611 return []
2612
2613
Peter Kasting4844e46e2018-02-23 07:27:102614def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532615 # Returns whether |template_str| is of the form <T, U...> for some types T
2616 # and U. Assumes that |template_str| is already in the form <...>.
2617 def HasMoreThanOneArg(template_str):
2618 # Level of <...> nesting.
2619 nesting = 0
2620 for c in template_str:
2621 if c == '<':
2622 nesting += 1
2623 elif c == '>':
2624 nesting -= 1
2625 elif c == ',' and nesting == 1:
2626 return True
2627 return False
2628
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492629 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102630 sources = lambda affected_file: input_api.FilterSourceFile(
2631 affected_file,
2632 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2633 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492634 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552635
2636 # Pattern to capture a single "<...>" block of template arguments. It can
2637 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2638 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2639 # latter would likely require counting that < and > match, which is not
2640 # expressible in regular languages. Should the need arise, one can introduce
2641 # limited counting (matching up to a total number of nesting depth), which
2642 # should cover all practical cases for already a low nesting limit.
2643 template_arg_pattern = (
2644 r'<[^>]*' # Opening block of <.
2645 r'>([^<]*>)?') # Closing block of >.
2646 # Prefix expressing that whatever follows is not already inside a <...>
2647 # block.
2648 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102649 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552650 not_inside_template_arg_pattern
2651 + r'\bstd::unique_ptr'
2652 + template_arg_pattern
2653 + r'\(\)')
2654
2655 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2656 template_arg_no_array_pattern = (
2657 r'<[^>]*[^]]' # Opening block of <.
2658 r'>([^(<]*[^]]>)?') # Closing block of >.
2659 # Prefix saying that what follows is the start of an expression.
2660 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2661 # Suffix saying that what follows are call parentheses with a non-empty list
2662 # of arguments.
2663 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532664 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552665 return_construct_pattern = input_api.re.compile(
2666 start_of_expr_pattern
2667 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532668 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552669 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532670 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552671 + nonempty_arg_list_pattern)
2672
Vaclav Brozek851d9602018-04-04 16:13:052673 problems_constructor = []
2674 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102675 for f in input_api.AffectedSourceFiles(sources):
2676 for line_number, line in f.ChangedContents():
2677 # Disallow:
2678 # return std::unique_ptr<T>(foo);
2679 # bar = std::unique_ptr<T>(foo);
2680 # But allow:
2681 # return std::unique_ptr<T[]>(foo);
2682 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532683 # And also allow cases when the second template argument is present. Those
2684 # cases cannot be handled by std::make_unique:
2685 # return std::unique_ptr<T, U>(foo);
2686 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052687 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532688 return_construct_result = return_construct_pattern.search(line)
2689 if return_construct_result and not HasMoreThanOneArg(
2690 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052691 problems_constructor.append(
2692 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102693 # Disallow:
2694 # std::unique_ptr<T>()
2695 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052696 problems_nullptr.append(
2697 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2698
2699 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162700 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052701 errors.append(output_api.PresubmitError(
2702 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162703 problems_nullptr))
2704 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052705 errors.append(output_api.PresubmitError(
2706 'The following files use explicit std::unique_ptr constructor.'
2707 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162708 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102709 return errors
2710
2711
[email protected]999261d2014-03-03 20:08:082712def _CheckUserActionUpdate(input_api, output_api):
2713 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522714 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082715 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522716 # If actions.xml is already included in the changelist, the PRESUBMIT
2717 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082718 return []
2719
[email protected]999261d2014-03-03 20:08:082720 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2721 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522722 current_actions = None
[email protected]999261d2014-03-03 20:08:082723 for f in input_api.AffectedFiles(file_filter=file_filter):
2724 for line_num, line in f.ChangedContents():
2725 match = input_api.re.search(action_re, line)
2726 if match:
[email protected]2f92dec2014-03-07 19:21:522727 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2728 # loaded only once.
2729 if not current_actions:
2730 with open('tools/metrics/actions/actions.xml') as actions_f:
2731 current_actions = actions_f.read()
2732 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082733 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522734 action = 'name="{0}"'.format(action_name)
2735 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082736 return [output_api.PresubmitPromptWarning(
2737 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522738 'tools/metrics/actions/actions.xml. Please run '
2739 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082740 % (f.LocalPath(), line_num, action_name))]
2741 return []
2742
2743
Daniel Cheng13ca61a882017-08-25 15:11:252744def _ImportJSONCommentEater(input_api):
2745 import sys
2746 sys.path = sys.path + [input_api.os_path.join(
2747 input_api.PresubmitLocalPath(),
2748 'tools', 'json_comment_eater')]
2749 import json_comment_eater
2750 return json_comment_eater
2751
2752
[email protected]99171a92014-06-03 08:44:472753def _GetJSONParseError(input_api, filename, eat_comments=True):
2754 try:
2755 contents = input_api.ReadFile(filename)
2756 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252757 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132758 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472759
2760 input_api.json.loads(contents)
2761 except ValueError as e:
2762 return e
2763 return None
2764
2765
2766def _GetIDLParseError(input_api, filename):
2767 try:
2768 contents = input_api.ReadFile(filename)
2769 idl_schema = input_api.os_path.join(
2770 input_api.PresubmitLocalPath(),
2771 'tools', 'json_schema_compiler', 'idl_schema.py')
2772 process = input_api.subprocess.Popen(
2773 [input_api.python_executable, idl_schema],
2774 stdin=input_api.subprocess.PIPE,
2775 stdout=input_api.subprocess.PIPE,
2776 stderr=input_api.subprocess.PIPE,
2777 universal_newlines=True)
2778 (_, error) = process.communicate(input=contents)
2779 return error or None
2780 except ValueError as e:
2781 return e
2782
2783
2784def _CheckParseErrors(input_api, output_api):
2785 """Check that IDL and JSON files do not contain syntax errors."""
2786 actions = {
2787 '.idl': _GetIDLParseError,
2788 '.json': _GetJSONParseError,
2789 }
[email protected]99171a92014-06-03 08:44:472790 # Most JSON files are preprocessed and support comments, but these do not.
2791 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042792 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472793 ]
2794 # Only run IDL checker on files in these directories.
2795 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042796 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2797 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472798 ]
2799
2800 def get_action(affected_file):
2801 filename = affected_file.LocalPath()
2802 return actions.get(input_api.os_path.splitext(filename)[1])
2803
[email protected]99171a92014-06-03 08:44:472804 def FilterFile(affected_file):
2805 action = get_action(affected_file)
2806 if not action:
2807 return False
2808 path = affected_file.LocalPath()
2809
Sean Kau46e29bc2017-08-28 16:31:162810 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472811 return False
2812
2813 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162814 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472815 return False
2816 return True
2817
2818 results = []
2819 for affected_file in input_api.AffectedFiles(
2820 file_filter=FilterFile, include_deletes=False):
2821 action = get_action(affected_file)
2822 kwargs = {}
2823 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162824 _MatchesFile(input_api, json_no_comments_patterns,
2825 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472826 kwargs['eat_comments'] = False
2827 parse_error = action(input_api,
2828 affected_file.AbsoluteLocalPath(),
2829 **kwargs)
2830 if parse_error:
2831 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2832 (affected_file.LocalPath(), parse_error)))
2833 return results
2834
2835
[email protected]760deea2013-12-10 19:33:492836def _CheckJavaStyle(input_api, output_api):
2837 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472838 import sys
[email protected]760deea2013-12-10 19:33:492839 original_sys_path = sys.path
2840 try:
2841 sys.path = sys.path + [input_api.os_path.join(
2842 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2843 import checkstyle
2844 finally:
2845 # Restore sys.path to what it was before.
2846 sys.path = original_sys_path
2847
2848 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092849 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512850 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492851
2852
Nate Fischerdfd9812e2019-07-18 22:03:002853def _CheckPythonDevilInit(input_api, output_api):
2854 """Checks to make sure devil is initialized correctly in python scripts."""
2855 script_common_initialize_pattern = input_api.re.compile(
2856 r'script_common\.InitializeEnvironment\(')
2857 devil_env_config_initialize = input_api.re.compile(
2858 r'devil_env\.config\.Initialize\(')
2859
2860 errors = []
2861
2862 sources = lambda affected_file: input_api.FilterSourceFile(
2863 affected_file,
2864 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2865 (r'^build[\\/]android[\\/]devil_chromium\.py',
2866 r'^third_party[\\/].*',)),
2867 white_list=[r'.*\.py$'])
2868
2869 for f in input_api.AffectedSourceFiles(sources):
2870 for line_num, line in f.ChangedContents():
2871 if (script_common_initialize_pattern.search(line) or
2872 devil_env_config_initialize.search(line)):
2873 errors.append("%s:%d" % (f.LocalPath(), line_num))
2874
2875 results = []
2876
2877 if errors:
2878 results.append(output_api.PresubmitError(
2879 'Devil initialization should always be done using '
2880 'devil_chromium.Initialize() in the chromium project, to use better '
2881 'defaults for dependencies (ex. up-to-date version of adb).',
2882 errors))
2883
2884 return results
2885
2886
Sean Kau46e29bc2017-08-28 16:31:162887def _MatchesFile(input_api, patterns, path):
2888 for pattern in patterns:
2889 if input_api.re.search(pattern, path):
2890 return True
2891 return False
2892
2893
Daniel Cheng7052cdf2017-11-21 19:23:292894def _GetOwnersFilesToCheckForIpcOwners(input_api):
2895 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172896
Daniel Cheng7052cdf2017-11-21 19:23:292897 Returns:
2898 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2899 contain to cover IPC-related files with noparent reviewer rules.
2900 """
2901 # Whether or not a file affects IPC is (mostly) determined by a simple list
2902 # of filename patterns.
dchenge07de812016-06-20 19:27:172903 file_patterns = [
palmerb19a0932017-01-24 04:00:312904 # Legacy IPC:
dchenge07de812016-06-20 19:27:172905 '*_messages.cc',
2906 '*_messages*.h',
2907 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312908 # Mojo IPC:
dchenge07de812016-06-20 19:27:172909 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472910 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172911 '*_struct_traits*.*',
2912 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312913 '*.typemap',
2914 # Android native IPC:
2915 '*.aidl',
2916 # Blink uses a different file naming convention:
2917 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472918 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172919 '*StructTraits*.*',
2920 '*TypeConverter*.*',
2921 ]
2922
scottmg7a6ed5ba2016-11-04 18:22:042923 # These third_party directories do not contain IPCs, but contain files
2924 # matching the above patterns, which trigger false positives.
2925 exclude_paths = [
2926 'third_party/crashpad/*',
Andres Medinae684cf42018-08-27 18:48:232927 'third_party/protobuf/benchmarks/python/*',
Daniel Chengebe635e2018-07-13 12:36:062928 'third_party/third_party/blink/renderer/platform/bindings/*',
Nico Weberee3dc9b2017-08-31 17:09:292929 'third_party/win_build_output/*',
Scott Violet9f82d362019-11-06 21:42:162930 # These files are just used to communicate between class loaders running
2931 # in the same process.
2932 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
scottmg7a6ed5ba2016-11-04 18:22:042933 ]
2934
dchenge07de812016-06-20 19:27:172935 # Dictionary mapping an OWNERS file path to Patterns.
2936 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2937 # rules ) to a PatternEntry.
2938 # PatternEntry is a dictionary with two keys:
2939 # - 'files': the files that are matched by this pattern
2940 # - 'rules': the per-file rules needed for this pattern
2941 # For example, if we expect OWNERS file to contain rules for *.mojom and
2942 # *_struct_traits*.*, Patterns might look like this:
2943 # {
2944 # '*.mojom': {
2945 # 'files': ...,
2946 # 'rules': [
2947 # 'per-file *.mojom=set noparent',
2948 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2949 # ],
2950 # },
2951 # '*_struct_traits*.*': {
2952 # 'files': ...,
2953 # 'rules': [
2954 # 'per-file *_struct_traits*.*=set noparent',
2955 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2956 # ],
2957 # },
2958 # }
2959 to_check = {}
2960
Daniel Cheng13ca61a882017-08-25 15:11:252961 def AddPatternToCheck(input_file, pattern):
2962 owners_file = input_api.os_path.join(
2963 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2964 if owners_file not in to_check:
2965 to_check[owners_file] = {}
2966 if pattern not in to_check[owners_file]:
2967 to_check[owners_file][pattern] = {
2968 'files': [],
2969 'rules': [
2970 'per-file %s=set noparent' % pattern,
2971 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2972 ]
2973 }
Vaclav Brozekd5de76a2018-03-17 07:57:502974 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252975
dchenge07de812016-06-20 19:27:172976 # Iterate through the affected files to see what we actually need to check
2977 # for. We should only nag patch authors about per-file rules if a file in that
2978 # directory would match that pattern. If a directory only contains *.mojom
2979 # files and no *_messages*.h files, we should only nag about rules for
2980 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252981 for f in input_api.AffectedFiles(include_deletes=False):
2982 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362983 # affected files for .json, .cc, and .h files which look like they contain
2984 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162985 if (f.LocalPath().endswith('.json') and
2986 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2987 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252988 json_comment_eater = _ImportJSONCommentEater(input_api)
2989 mostly_json_lines = '\n'.join(f.NewContents())
2990 # Comments aren't allowed in strict JSON, so filter them out.
2991 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432992 try:
2993 json_content = input_api.json.loads(json_lines)
2994 except:
2995 # There's another PRESUBMIT check that already verifies that JSON files
2996 # are not invalid, so no need to emit another warning here.
2997 continue
Daniel Cheng13ca61a882017-08-25 15:11:252998 if 'interface_provider_specs' in json_content:
2999 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:363000 else:
3001 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
3002 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
3003 if (manifest_pattern.search(f.LocalPath()) and not
3004 test_manifest_pattern.search(f.LocalPath())):
3005 # We expect all actual service manifest files to contain at least one
3006 # qualified reference to service_manager::Manifest.
3007 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
3008 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:173009 for pattern in file_patterns:
3010 if input_api.fnmatch.fnmatch(
3011 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:043012 skip = False
3013 for exclude in exclude_paths:
3014 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
3015 skip = True
3016 break
3017 if skip:
3018 continue
Daniel Cheng13ca61a882017-08-25 15:11:253019 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:173020 break
3021
Daniel Cheng7052cdf2017-11-21 19:23:293022 return to_check
3023
3024
3025def _CheckIpcOwners(input_api, output_api):
3026 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3027 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
3028
3029 if to_check:
3030 # If there are any OWNERS files to check, there are IPC-related changes in
3031 # this CL. Auto-CC the review list.
3032 output_api.AppendCC('[email protected]')
3033
3034 # Go through the OWNERS files to check, filtering out rules that are already
3035 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173036 for owners_file, patterns in to_check.iteritems():
3037 try:
3038 with file(owners_file) as f:
3039 lines = set(f.read().splitlines())
3040 for entry in patterns.itervalues():
3041 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3042 ]
3043 except IOError:
3044 # No OWNERS file, so all the rules are definitely missing.
3045 continue
3046
3047 # All the remaining lines weren't found in OWNERS files, so emit an error.
3048 errors = []
3049 for owners_file, patterns in to_check.iteritems():
3050 missing_lines = []
3051 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503052 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173053 missing_lines.extend(entry['rules'])
3054 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3055 if missing_lines:
3056 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053057 'Because of the presence of files:\n%s\n\n'
3058 '%s needs the following %d lines added:\n\n%s' %
3059 ('\n'.join(files), owners_file, len(missing_lines),
3060 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173061
3062 results = []
3063 if errors:
vabrf5ce3bf92016-07-11 14:52:413064 if input_api.is_committing:
3065 output = output_api.PresubmitError
3066 else:
3067 output = output_api.PresubmitPromptWarning
3068 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593069 'Found OWNERS files that need to be updated for IPC security ' +
3070 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173071 long_text='\n\n'.join(errors)))
3072
3073 return results
3074
3075
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263076def _CheckSetNoParent(input_api, output_api):
3077 """Checks that set noparent is only used together with an OWNERS file in
3078 //build/OWNERS.setnoparent (see also
3079 //docs/code_reviews.md#owners-files-details)
3080 """
3081 errors = []
3082
3083 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3084 allowed_owners_files = set()
3085 with open(allowed_owners_files_file, 'r') as f:
3086 for line in f:
3087 line = line.strip()
3088 if not line or line.startswith('#'):
3089 continue
3090 allowed_owners_files.add(line)
3091
3092 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3093
3094 for f in input_api.AffectedFiles(include_deletes=False):
3095 if not f.LocalPath().endswith('OWNERS'):
3096 continue
3097
3098 found_owners_files = set()
3099 found_set_noparent_lines = dict()
3100
3101 # Parse the OWNERS file.
3102 for lineno, line in enumerate(f.NewContents(), 1):
3103 line = line.strip()
3104 if line.startswith('set noparent'):
3105 found_set_noparent_lines[''] = lineno
3106 if line.startswith('file://'):
3107 if line in allowed_owners_files:
3108 found_owners_files.add('')
3109 if line.startswith('per-file'):
3110 match = per_file_pattern.match(line)
3111 if match:
3112 glob = match.group(1).strip()
3113 directive = match.group(2).strip()
3114 if directive == 'set noparent':
3115 found_set_noparent_lines[glob] = lineno
3116 if directive.startswith('file://'):
3117 if directive in allowed_owners_files:
3118 found_owners_files.add(glob)
3119
3120 # Check that every set noparent line has a corresponding file:// line
3121 # listed in build/OWNERS.setnoparent.
3122 for set_noparent_line in found_set_noparent_lines:
3123 if set_noparent_line in found_owners_files:
3124 continue
3125 errors.append(' %s:%d' % (f.LocalPath(),
3126 found_set_noparent_lines[set_noparent_line]))
3127
3128 results = []
3129 if errors:
3130 if input_api.is_committing:
3131 output = output_api.PresubmitError
3132 else:
3133 output = output_api.PresubmitPromptWarning
3134 results.append(output(
3135 'Found the following "set noparent" restrictions in OWNERS files that '
3136 'do not include owners from build/OWNERS.setnoparent:',
3137 long_text='\n\n'.join(errors)))
3138 return results
3139
3140
jbriance9e12f162016-11-25 07:57:503141def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313142 """Checks that added or removed lines in non third party affected
3143 header files do not lead to new useless class or struct forward
3144 declaration.
jbriance9e12f162016-11-25 07:57:503145 """
3146 results = []
3147 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3148 input_api.re.MULTILINE)
3149 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3150 input_api.re.MULTILINE)
3151 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313152 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193153 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493154 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313155 continue
3156
jbriance9e12f162016-11-25 07:57:503157 if not f.LocalPath().endswith('.h'):
3158 continue
3159
3160 contents = input_api.ReadFile(f)
3161 fwd_decls = input_api.re.findall(class_pattern, contents)
3162 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3163
3164 useless_fwd_decls = []
3165 for decl in fwd_decls:
3166 count = sum(1 for _ in input_api.re.finditer(
3167 r'\b%s\b' % input_api.re.escape(decl), contents))
3168 if count == 1:
3169 useless_fwd_decls.append(decl)
3170
3171 if not useless_fwd_decls:
3172 continue
3173
3174 for line in f.GenerateScmDiff().splitlines():
3175 if (line.startswith('-') and not line.startswith('--') or
3176 line.startswith('+') and not line.startswith('++')):
3177 for decl in useless_fwd_decls:
3178 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3179 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243180 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503181 (f.LocalPath(), decl)))
3182 useless_fwd_decls.remove(decl)
3183
3184 return results
3185
Jinsong Fan91ebbbd2019-04-16 14:57:173186def _CheckAndroidDebuggableBuild(input_api, output_api):
3187 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3188 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3189 this is a debuggable build of Android.
3190 """
3191 build_type_check_pattern = input_api.re.compile(
3192 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3193
3194 errors = []
3195
3196 sources = lambda affected_file: input_api.FilterSourceFile(
3197 affected_file,
3198 black_list=(_EXCLUDED_PATHS +
3199 _TEST_CODE_EXCLUDED_PATHS +
3200 input_api.DEFAULT_BLACK_LIST +
3201 (r"^android_webview[\\/]support_library[\\/]"
3202 "boundary_interfaces[\\/]",
3203 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3204 r'^third_party[\\/].*',
3205 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3206 r"webview[\\/]chromium[\\/]License.*",)),
3207 white_list=[r'.*\.java$'])
3208
3209 for f in input_api.AffectedSourceFiles(sources):
3210 for line_num, line in f.ChangedContents():
3211 if build_type_check_pattern.search(line):
3212 errors.append("%s:%d" % (f.LocalPath(), line_num))
3213
3214 results = []
3215
3216 if errors:
3217 results.append(output_api.PresubmitPromptWarning(
3218 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3219 ' Please use BuildInfo.isDebugAndroid() instead.',
3220 errors))
3221
3222 return results
jbriance9e12f162016-11-25 07:57:503223
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493224# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293225def _CheckAndroidToastUsage(input_api, output_api):
3226 """Checks that code uses org.chromium.ui.widget.Toast instead of
3227 android.widget.Toast (Chromium Toast doesn't force hardware
3228 acceleration on low-end devices, saving memory).
3229 """
3230 toast_import_pattern = input_api.re.compile(
3231 r'^import android\.widget\.Toast;$')
3232
3233 errors = []
3234
3235 sources = lambda affected_file: input_api.FilterSourceFile(
3236 affected_file,
3237 black_list=(_EXCLUDED_PATHS +
3238 _TEST_CODE_EXCLUDED_PATHS +
3239 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043240 (r'^chromecast[\\/].*',
3241 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493242 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293243
3244 for f in input_api.AffectedSourceFiles(sources):
3245 for line_num, line in f.ChangedContents():
3246 if toast_import_pattern.search(line):
3247 errors.append("%s:%d" % (f.LocalPath(), line_num))
3248
3249 results = []
3250
3251 if errors:
3252 results.append(output_api.PresubmitError(
3253 'android.widget.Toast usage is detected. Android toasts use hardware'
3254 ' acceleration, and can be\ncostly on low-end devices. Please use'
3255 ' org.chromium.ui.widget.Toast instead.\n'
3256 'Contact [email protected] if you have any questions.',
3257 errors))
3258
3259 return results
3260
3261
dgnaa68d5e2015-06-10 10:08:223262def _CheckAndroidCrLogUsage(input_api, output_api):
3263 """Checks that new logs using org.chromium.base.Log:
3264 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513265 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223266 """
pkotwicza1dd0b002016-05-16 14:41:043267
torne89540622017-03-24 19:41:303268 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043269 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303270 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043271 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303272 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043273 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3274 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093275 # The customtabs_benchmark is a small app that does not depend on Chromium
3276 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043277 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043278 ]
3279
dgnaa68d5e2015-06-10 10:08:223280 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123281 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3282 class_in_base_pattern = input_api.re.compile(
3283 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3284 has_some_log_import_pattern = input_api.re.compile(
3285 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223286 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123287 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223288 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463289 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223290
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463291 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493292 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043293 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123294
dgnaa68d5e2015-06-10 10:08:223295 tag_decl_errors = []
3296 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123297 tag_errors = []
dgn38736db2015-09-18 19:20:513298 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123299 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223300
3301 for f in input_api.AffectedSourceFiles(sources):
3302 file_content = input_api.ReadFile(f)
3303 has_modified_logs = False
3304
3305 # Per line checks
dgn87d9fb62015-06-12 09:15:123306 if (cr_log_import_pattern.search(file_content) or
3307 (class_in_base_pattern.search(file_content) and
3308 not has_some_log_import_pattern.search(file_content))):
3309 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223310 for line_num, line in f.ChangedContents():
3311
3312 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123313 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223314 if match:
3315 has_modified_logs = True
3316
3317 # Make sure it uses "TAG"
3318 if not match.group('tag') == 'TAG':
3319 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123320 else:
3321 # Report non cr Log function calls in changed lines
3322 for line_num, line in f.ChangedContents():
3323 if log_call_pattern.search(line):
3324 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223325
3326 # Per file checks
3327 if has_modified_logs:
3328 # Make sure the tag is using the "cr" prefix and is not too long
3329 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513330 tag_name = match.group('name') if match else None
3331 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223332 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513333 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223334 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513335 elif '.' in tag_name:
3336 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223337
3338 results = []
3339 if tag_decl_errors:
3340 results.append(output_api.PresubmitPromptWarning(
3341 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513342 '"private static final String TAG = "<package tag>".\n'
3343 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223344 tag_decl_errors))
3345
3346 if tag_length_errors:
3347 results.append(output_api.PresubmitError(
3348 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513349 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223350 tag_length_errors))
3351
3352 if tag_errors:
3353 results.append(output_api.PresubmitPromptWarning(
3354 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3355 tag_errors))
3356
dgn87d9fb62015-06-12 09:15:123357 if util_log_errors:
dgn4401aa52015-04-29 16:26:173358 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123359 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3360 util_log_errors))
3361
dgn38736db2015-09-18 19:20:513362 if tag_with_dot_errors:
3363 results.append(output_api.PresubmitPromptWarning(
3364 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3365 tag_with_dot_errors))
3366
dgn4401aa52015-04-29 16:26:173367 return results
3368
3369
Yoland Yanb92fa522017-08-28 17:37:063370def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3371 """Checks that junit.framework.* is no longer used."""
3372 deprecated_junit_framework_pattern = input_api.re.compile(
3373 r'^import junit\.framework\..*;',
3374 input_api.re.MULTILINE)
3375 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493376 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063377 errors = []
3378 for f in input_api.AffectedFiles(sources):
3379 for line_num, line in f.ChangedContents():
3380 if deprecated_junit_framework_pattern.search(line):
3381 errors.append("%s:%d" % (f.LocalPath(), line_num))
3382
3383 results = []
3384 if errors:
3385 results.append(output_api.PresubmitError(
3386 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3387 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3388 ' if you have any question.', errors))
3389 return results
3390
3391
3392def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3393 """Checks that if new Java test classes have inheritance.
3394 Either the new test class is JUnit3 test or it is a JUnit4 test class
3395 with a base class, either case is undesirable.
3396 """
3397 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3398
3399 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493400 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063401 errors = []
3402 for f in input_api.AffectedFiles(sources):
3403 if not f.OldContents():
3404 class_declaration_start_flag = False
3405 for line_num, line in f.ChangedContents():
3406 if class_declaration_pattern.search(line):
3407 class_declaration_start_flag = True
3408 if class_declaration_start_flag and ' extends ' in line:
3409 errors.append('%s:%d' % (f.LocalPath(), line_num))
3410 if '{' in line:
3411 class_declaration_start_flag = False
3412
3413 results = []
3414 if errors:
3415 results.append(output_api.PresubmitPromptWarning(
3416 'The newly created files include Test classes that inherits from base'
3417 ' class. Please do not use inheritance in JUnit4 tests or add new'
3418 ' JUnit3 tests. Contact [email protected] if you have any'
3419 ' questions.', errors))
3420 return results
3421
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203422
yolandyan45001472016-12-21 21:12:423423def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3424 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3425 deprecated_annotation_import_pattern = input_api.re.compile(
3426 r'^import android\.test\.suitebuilder\.annotation\..*;',
3427 input_api.re.MULTILINE)
3428 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493429 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423430 errors = []
3431 for f in input_api.AffectedFiles(sources):
3432 for line_num, line in f.ChangedContents():
3433 if deprecated_annotation_import_pattern.search(line):
3434 errors.append("%s:%d" % (f.LocalPath(), line_num))
3435
3436 results = []
3437 if errors:
3438 results.append(output_api.PresubmitError(
3439 'Annotations in android.test.suitebuilder.annotation have been'
3440 ' deprecated since API level 24. Please use android.support.test.filters'
3441 ' from //third_party/android_support_test_runner:runner_java instead.'
3442 ' Contact [email protected] if you have any questions.', errors))
3443 return results
3444
3445
agrieve7b6479d82015-10-07 14:24:223446def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3447 """Checks if MDPI assets are placed in a correct directory."""
3448 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3449 ('/res/drawable/' in f.LocalPath() or
3450 '/res/drawable-ldrtl/' in f.LocalPath()))
3451 errors = []
3452 for f in input_api.AffectedFiles(include_deletes=False,
3453 file_filter=file_filter):
3454 errors.append(' %s' % f.LocalPath())
3455
3456 results = []
3457 if errors:
3458 results.append(output_api.PresubmitError(
3459 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3460 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3461 '/res/drawable-ldrtl/.\n'
3462 'Contact [email protected] if you have questions.', errors))
3463 return results
3464
3465
Nate Fischer535972b2017-09-16 01:06:183466def _CheckAndroidWebkitImports(input_api, output_api):
3467 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353468 android.webview.ValueCallback except in the WebView glue layer
3469 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183470 """
3471 valuecallback_import_pattern = input_api.re.compile(
3472 r'^import android\.webkit\.ValueCallback;$')
3473
3474 errors = []
3475
3476 sources = lambda affected_file: input_api.FilterSourceFile(
3477 affected_file,
3478 black_list=(_EXCLUDED_PATHS +
3479 _TEST_CODE_EXCLUDED_PATHS +
3480 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353481 (r'^android_webview[\\/]glue[\\/].*',
3482 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493483 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183484
3485 for f in input_api.AffectedSourceFiles(sources):
3486 for line_num, line in f.ChangedContents():
3487 if valuecallback_import_pattern.search(line):
3488 errors.append("%s:%d" % (f.LocalPath(), line_num))
3489
3490 results = []
3491
3492 if errors:
3493 results.append(output_api.PresubmitError(
3494 'android.webkit.ValueCallback usage is detected outside of the glue'
3495 ' layer. To stay compatible with the support library, android.webkit.*'
3496 ' classes should only be used inside the glue layer and'
3497 ' org.chromium.base.Callback should be used instead.',
3498 errors))
3499
3500 return results
3501
3502
Becky Zhou7c69b50992018-12-10 19:37:573503def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3504 """Checks Android XML styles """
3505 import sys
3506 original_sys_path = sys.path
3507 try:
3508 sys.path = sys.path + [input_api.os_path.join(
3509 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3510 import checkxmlstyle
3511 finally:
3512 # Restore sys.path to what it was before.
3513 sys.path = original_sys_path
3514
3515 if is_check_on_upload:
3516 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3517 else:
3518 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3519
3520
agrievef32bcc72016-04-04 14:57:403521class PydepsChecker(object):
3522 def __init__(self, input_api, pydeps_files):
3523 self._file_cache = {}
3524 self._input_api = input_api
3525 self._pydeps_files = pydeps_files
3526
3527 def _LoadFile(self, path):
3528 """Returns the list of paths within a .pydeps file relative to //."""
3529 if path not in self._file_cache:
3530 with open(path) as f:
3531 self._file_cache[path] = f.read()
3532 return self._file_cache[path]
3533
3534 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3535 """Returns an interable of paths within the .pydep, relativized to //."""
3536 os_path = self._input_api.os_path
3537 pydeps_dir = os_path.dirname(pydeps_path)
3538 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3539 if not l.startswith('*'))
3540 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3541
3542 def _CreateFilesToPydepsMap(self):
3543 """Returns a map of local_path -> list_of_pydeps."""
3544 ret = {}
3545 for pydep_local_path in self._pydeps_files:
3546 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3547 ret.setdefault(path, []).append(pydep_local_path)
3548 return ret
3549
3550 def ComputeAffectedPydeps(self):
3551 """Returns an iterable of .pydeps files that might need regenerating."""
3552 affected_pydeps = set()
3553 file_to_pydeps_map = None
3554 for f in self._input_api.AffectedFiles(include_deletes=True):
3555 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463556 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3557 # subrepositories. We can't figure out which files change, so re-check
3558 # all files.
3559 # Changes to print_python_deps.py affect all .pydeps.
3560 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403561 return self._pydeps_files
3562 elif local_path.endswith('.pydeps'):
3563 if local_path in self._pydeps_files:
3564 affected_pydeps.add(local_path)
3565 elif local_path.endswith('.py'):
3566 if file_to_pydeps_map is None:
3567 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3568 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3569 return affected_pydeps
3570
3571 def DetermineIfStale(self, pydeps_path):
3572 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413573 import difflib
John Budorick47ca3fe2018-02-10 00:53:103574 import os
3575
agrievef32bcc72016-04-04 14:57:403576 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3577 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103578 env = dict(os.environ)
3579 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403580 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103581 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413582 old_contents = old_pydeps_data[2:]
3583 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403584 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413585 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403586
3587
Tibor Goldschwendt360793f72019-06-25 18:23:493588def _ParseGclientArgs():
3589 args = {}
3590 with open('build/config/gclient_args.gni', 'r') as f:
3591 for line in f:
3592 line = line.strip()
3593 if not line or line.startswith('#'):
3594 continue
3595 attribute, value = line.split('=')
3596 args[attribute.strip()] = value.strip()
3597 return args
3598
3599
agrievef32bcc72016-04-04 14:57:403600def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3601 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403602 # This check is for Python dependency lists (.pydeps files), and involves
3603 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3604 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283605 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003606 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493607 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403608 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3609 results = []
3610 # First, check for new / deleted .pydeps.
3611 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033612 # Check whether we are running the presubmit check for a file in src.
3613 # f.LocalPath is relative to repo (src, or internal repo).
3614 # os_path.exists is relative to src repo.
3615 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3616 # to src and we can conclude that the pydeps is in src.
3617 if input_api.os_path.exists(f.LocalPath()):
3618 if f.LocalPath().endswith('.pydeps'):
3619 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3620 results.append(output_api.PresubmitError(
3621 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3622 'remove %s' % f.LocalPath()))
3623 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3624 results.append(output_api.PresubmitError(
3625 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3626 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403627
3628 if results:
3629 return results
3630
3631 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3632
3633 for pydep_path in checker.ComputeAffectedPydeps():
3634 try:
phajdan.jr0d9878552016-11-04 10:49:413635 result = checker.DetermineIfStale(pydep_path)
3636 if result:
3637 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403638 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413639 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3640 'To regenerate, run:\n\n %s' %
3641 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403642 except input_api.subprocess.CalledProcessError as error:
3643 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3644 long_text=error.output)]
3645
3646 return results
3647
3648
glidere61efad2015-02-18 17:39:433649def _CheckSingletonInHeaders(input_api, output_api):
3650 """Checks to make sure no header files have |Singleton<|."""
3651 def FileFilter(affected_file):
3652 # It's ok for base/memory/singleton.h to have |Singleton<|.
3653 black_list = (_EXCLUDED_PATHS +
3654 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043655 (r"^base[\\/]memory[\\/]singleton\.h$",
3656 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473657 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433658 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3659
sergeyu34d21222015-09-16 00:11:443660 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433661 files = []
3662 for f in input_api.AffectedSourceFiles(FileFilter):
3663 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3664 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3665 contents = input_api.ReadFile(f)
3666 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243667 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433668 pattern.search(line)):
3669 files.append(f)
3670 break
3671
3672 if files:
yolandyandaabc6d2016-04-18 18:29:393673 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443674 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433675 'Please move them to an appropriate source file so that the ' +
3676 'template gets instantiated in a single compilation unit.',
3677 files) ]
3678 return []
3679
3680
[email protected]fd20b902014-05-09 02:14:533681_DEPRECATED_CSS = [
3682 # Values
3683 ( "-webkit-box", "flex" ),
3684 ( "-webkit-inline-box", "inline-flex" ),
3685 ( "-webkit-flex", "flex" ),
3686 ( "-webkit-inline-flex", "inline-flex" ),
3687 ( "-webkit-min-content", "min-content" ),
3688 ( "-webkit-max-content", "max-content" ),
3689
3690 # Properties
3691 ( "-webkit-background-clip", "background-clip" ),
3692 ( "-webkit-background-origin", "background-origin" ),
3693 ( "-webkit-background-size", "background-size" ),
3694 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443695 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533696
3697 # Functions
3698 ( "-webkit-gradient", "gradient" ),
3699 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3700 ( "-webkit-linear-gradient", "linear-gradient" ),
3701 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3702 ( "-webkit-radial-gradient", "radial-gradient" ),
3703 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3704]
3705
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203706
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493707# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243708def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533709 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253710 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343711 documentation and iOS CSS for dom distiller
3712 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253713 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533714 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493715 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253716 black_list = (_EXCLUDED_PATHS +
3717 _TEST_CODE_EXCLUDED_PATHS +
3718 input_api.DEFAULT_BLACK_LIST +
3719 (r"^chrome/common/extensions/docs",
3720 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343721 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443722 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253723 r"^native_client_sdk"))
3724 file_filter = lambda f: input_api.FilterSourceFile(
3725 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533726 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3727 for line_num, line in fpath.ChangedContents():
3728 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023729 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533730 results.append(output_api.PresubmitError(
3731 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3732 (fpath.LocalPath(), line_num, deprecated_value, value)))
3733 return results
3734
mohan.reddyf21db962014-10-16 12:26:473735
rlanday6802cf632017-05-30 17:48:363736def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363737 bad_files = {}
3738 for f in input_api.AffectedFiles(include_deletes=False):
3739 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493740 not f.LocalPath().startswith('third_party/blink') and
3741 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363742 continue
3743
Daniel Bratell65b033262019-04-23 08:17:063744 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363745 continue
3746
Vaclav Brozekd5de76a2018-03-17 07:57:503747 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363748 if "#include" in line and "../" in line]
3749 if not relative_includes:
3750 continue
3751 bad_files[f.LocalPath()] = relative_includes
3752
3753 if not bad_files:
3754 return []
3755
3756 error_descriptions = []
3757 for file_path, bad_lines in bad_files.iteritems():
3758 error_description = file_path
3759 for line in bad_lines:
3760 error_description += '\n ' + line
3761 error_descriptions.append(error_description)
3762
3763 results = []
3764 results.append(output_api.PresubmitError(
3765 'You added one or more relative #include paths (including "../").\n'
3766 'These shouldn\'t be used because they can be used to include headers\n'
3767 'from code that\'s not correctly specified as a dependency in the\n'
3768 'relevant BUILD.gn file(s).',
3769 error_descriptions))
3770
3771 return results
3772
Takeshi Yoshinoe387aa32017-08-02 13:16:133773
Daniel Bratell65b033262019-04-23 08:17:063774def _CheckForCcIncludes(input_api, output_api):
3775 """Check that nobody tries to include a cc file. It's a relatively
3776 common error which results in duplicate symbols in object
3777 files. This may not always break the build until someone later gets
3778 very confusing linking errors."""
3779 results = []
3780 for f in input_api.AffectedFiles(include_deletes=False):
3781 # We let third_party code do whatever it wants
3782 if (f.LocalPath().startswith('third_party') and
3783 not f.LocalPath().startswith('third_party/blink') and
3784 not f.LocalPath().startswith('third_party\\blink')):
3785 continue
3786
3787 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3788 continue
3789
3790 for _, line in f.ChangedContents():
3791 if line.startswith('#include "'):
3792 included_file = line.split('"')[1]
3793 if _IsCPlusPlusFile(input_api, included_file):
3794 # The most common naming for external files with C++ code,
3795 # apart from standard headers, is to call them foo.inc, but
3796 # Chromium sometimes uses foo-inc.cc so allow that as well.
3797 if not included_file.endswith(('.h', '-inc.cc')):
3798 results.append(output_api.PresubmitError(
3799 'Only header files or .inc files should be included in other\n'
3800 'C++ files. Compiling the contents of a cc file more than once\n'
3801 'will cause duplicate information in the build which may later\n'
3802 'result in strange link_errors.\n' +
3803 f.LocalPath() + ':\n ' +
3804 line))
3805
3806 return results
3807
3808
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203809def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3810 if not isinstance(key, ast.Str):
3811 return 'Key at line %d must be a string literal' % key.lineno
3812 if not isinstance(value, ast.Dict):
3813 return 'Value at line %d must be a dict' % value.lineno
3814 if len(value.keys) != 1:
3815 return 'Dict at line %d must have single entry' % value.lineno
3816 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3817 return (
3818 'Entry at line %d must have a string literal \'filepath\' as key' %
3819 value.lineno)
3820 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133821
Takeshi Yoshinoe387aa32017-08-02 13:16:133822
Sergey Ulanov4af16052018-11-08 02:41:463823def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203824 if not isinstance(key, ast.Str):
3825 return 'Key at line %d must be a string literal' % key.lineno
3826 if not isinstance(value, ast.List):
3827 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463828 for element in value.elts:
3829 if not isinstance(element, ast.Str):
3830 return 'Watchlist elements on line %d is not a string' % key.lineno
3831 if not email_regex.match(element.s):
3832 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3833 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203834 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133835
Takeshi Yoshinoe387aa32017-08-02 13:16:133836
Sergey Ulanov4af16052018-11-08 02:41:463837def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203838 mismatch_template = (
3839 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3840 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133841
Sergey Ulanov4af16052018-11-08 02:41:463842 email_regex = input_api.re.compile(
3843 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3844
3845 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203846 i = 0
3847 last_key = ''
3848 while True:
3849 if i >= len(wd_dict.keys):
3850 if i >= len(w_dict.keys):
3851 return None
3852 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3853 elif i >= len(w_dict.keys):
3854 return (
3855 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133856
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203857 wd_key = wd_dict.keys[i]
3858 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133859
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203860 result = _CheckWatchlistDefinitionsEntrySyntax(
3861 wd_key, wd_dict.values[i], ast)
3862 if result is not None:
3863 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133864
Sergey Ulanov4af16052018-11-08 02:41:463865 result = _CheckWatchlistsEntrySyntax(
3866 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203867 if result is not None:
3868 return 'Bad entry in WATCHLISTS dict: %s' % result
3869
3870 if wd_key.s != w_key.s:
3871 return mismatch_template % (
3872 '%s at line %d' % (wd_key.s, wd_key.lineno),
3873 '%s at line %d' % (w_key.s, w_key.lineno))
3874
3875 if wd_key.s < last_key:
3876 return (
3877 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3878 (wd_key.lineno, w_key.lineno))
3879 last_key = wd_key.s
3880
3881 i = i + 1
3882
3883
Sergey Ulanov4af16052018-11-08 02:41:463884def _CheckWATCHLISTSSyntax(expression, input_api):
3885 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203886 if not isinstance(expression, ast.Expression):
3887 return 'WATCHLISTS file must contain a valid expression'
3888 dictionary = expression.body
3889 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3890 return 'WATCHLISTS file must have single dict with exactly two entries'
3891
3892 first_key = dictionary.keys[0]
3893 first_value = dictionary.values[0]
3894 second_key = dictionary.keys[1]
3895 second_value = dictionary.values[1]
3896
3897 if (not isinstance(first_key, ast.Str) or
3898 first_key.s != 'WATCHLIST_DEFINITIONS' or
3899 not isinstance(first_value, ast.Dict)):
3900 return (
3901 'The first entry of the dict in WATCHLISTS file must be '
3902 'WATCHLIST_DEFINITIONS dict')
3903
3904 if (not isinstance(second_key, ast.Str) or
3905 second_key.s != 'WATCHLISTS' or
3906 not isinstance(second_value, ast.Dict)):
3907 return (
3908 'The second entry of the dict in WATCHLISTS file must be '
3909 'WATCHLISTS dict')
3910
Sergey Ulanov4af16052018-11-08 02:41:463911 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133912
3913
3914def _CheckWATCHLISTS(input_api, output_api):
3915 for f in input_api.AffectedFiles(include_deletes=False):
3916 if f.LocalPath() == 'WATCHLISTS':
3917 contents = input_api.ReadFile(f, 'r')
3918
3919 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203920 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133921 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203922 # Get an AST tree for it and scan the tree for detailed style checking.
3923 expression = input_api.ast.parse(
3924 contents, filename='WATCHLISTS', mode='eval')
3925 except ValueError as e:
3926 return [output_api.PresubmitError(
3927 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3928 except SyntaxError as e:
3929 return [output_api.PresubmitError(
3930 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3931 except TypeError as e:
3932 return [output_api.PresubmitError(
3933 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133934
Sergey Ulanov4af16052018-11-08 02:41:463935 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203936 if result is not None:
3937 return [output_api.PresubmitError(result)]
3938 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133939
3940 return []
3941
3942
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193943def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3944 """Checks that newly added header files have corresponding GN changes.
3945 Note that this is only a heuristic. To be precise, run script:
3946 build/check_gn_headers.py.
3947 """
3948
3949 def headers(f):
3950 return input_api.FilterSourceFile(
3951 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3952
3953 new_headers = []
3954 for f in input_api.AffectedSourceFiles(headers):
3955 if f.Action() != 'A':
3956 continue
3957 new_headers.append(f.LocalPath())
3958
3959 def gn_files(f):
3960 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3961
3962 all_gn_changed_contents = ''
3963 for f in input_api.AffectedSourceFiles(gn_files):
3964 for _, line in f.ChangedContents():
3965 all_gn_changed_contents += line
3966
3967 problems = []
3968 for header in new_headers:
3969 basename = input_api.os_path.basename(header)
3970 if basename not in all_gn_changed_contents:
3971 problems.append(header)
3972
3973 if problems:
3974 return [output_api.PresubmitPromptWarning(
3975 'Missing GN changes for new header files', items=sorted(problems),
3976 long_text='Please double check whether newly added header files need '
3977 'corresponding changes in gn or gni files.\nThis checking is only a '
3978 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3979 'Read https://crbug.com/661774 for more info.')]
3980 return []
3981
3982
Michael Giuffridad3bc8672018-10-25 22:48:023983def _CheckCorrectProductNameInMessages(input_api, output_api):
3984 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3985
3986 This assumes we won't intentionally reference one product from the other
3987 product.
3988 """
3989 all_problems = []
3990 test_cases = [{
3991 "filename_postfix": "google_chrome_strings.grd",
3992 "correct_name": "Chrome",
3993 "incorrect_name": "Chromium",
3994 }, {
3995 "filename_postfix": "chromium_strings.grd",
3996 "correct_name": "Chromium",
3997 "incorrect_name": "Chrome",
3998 }]
3999
4000 for test_case in test_cases:
4001 problems = []
4002 filename_filter = lambda x: x.LocalPath().endswith(
4003 test_case["filename_postfix"])
4004
4005 # Check each new line. Can yield false positives in multiline comments, but
4006 # easier than trying to parse the XML because messages can have nested
4007 # children, and associating message elements with affected lines is hard.
4008 for f in input_api.AffectedSourceFiles(filename_filter):
4009 for line_num, line in f.ChangedContents():
4010 if "<message" in line or "<!--" in line or "-->" in line:
4011 continue
4012 if test_case["incorrect_name"] in line:
4013 problems.append(
4014 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
4015
4016 if problems:
4017 message = (
4018 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
4019 % (test_case["correct_name"], test_case["correct_name"],
4020 test_case["incorrect_name"]))
4021 all_problems.append(
4022 output_api.PresubmitPromptWarning(message, items=problems))
4023
4024 return all_problems
4025
4026
Dirk Pranke3c18a382019-03-15 01:07:514027def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4028 # TODO(crbug.com/941824): We need to make sure the entries in
4029 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4030 # so that users of //buildtools in other projects get the same tooling
4031 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4032 # support to gclient, we can eliminate the duplication and delete
4033 # this presubmit check.
4034
4035 # Update this regexp if new revisions are added to the files.
4036 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:014037 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:514038
4039 # If a user is changing one revision, they need to change the same
4040 # line in both files. This means that any given change should contain
4041 # exactly the same list of changed lines that match the regexps. The
4042 # replace(' ', '') call allows us to ignore whitespace changes to the
4043 # lines. The 'long_text' parameter to the error will contain the
4044 # list of changed lines in both files, which should make it easy enough
4045 # to spot the error without going overboard in this implementation.
4046 revs_changes = {
4047 'DEPS': {},
4048 'buildtools/DEPS': {},
4049 }
4050 long_text = ''
4051
4052 for f in input_api.AffectedFiles(
4053 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4054 for line_num, line in f.ChangedContents():
4055 if rev_regexp.search(line):
4056 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4057 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4058
4059 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4060 return [output_api.PresubmitError(
4061 'Change buildtools revisions in sync in both //DEPS and '
4062 '//buildtools/DEPS.', long_text=long_text + '\n')]
4063 else:
4064 return []
4065
4066
Daniel Bratell93eb6c62019-04-29 20:13:364067def _CheckForTooLargeFiles(input_api, output_api):
4068 """Avoid large files, especially binary files, in the repository since
4069 git doesn't scale well for those. They will be in everyone's repo
4070 clones forever, forever making Chromium slower to clone and work
4071 with."""
4072
4073 # Uploading files to cloud storage is not trivial so we don't want
4074 # to set the limit too low, but the upper limit for "normal" large
4075 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4076 # anything over 20 MB is exceptional.
4077 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4078
4079 too_large_files = []
4080 for f in input_api.AffectedFiles():
4081 # Check both added and modified files (but not deleted files).
4082 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384083 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364084 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4085 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4086
4087 if too_large_files:
4088 message = (
4089 'Do not commit large files to git since git scales badly for those.\n' +
4090 'Instead put the large files in cloud storage and use DEPS to\n' +
4091 'fetch them.\n' + '\n'.join(too_large_files)
4092 )
4093 return [output_api.PresubmitError(
4094 'Too large files found in commit', long_text=message + '\n')]
4095 else:
4096 return []
4097
Max Morozb47503b2019-08-08 21:03:274098
4099def _CheckFuzzTargets(input_api, output_api):
4100 """Checks specific for fuzz target sources."""
4101 EXPORTED_SYMBOLS = [
4102 'LLVMFuzzerInitialize',
4103 'LLVMFuzzerCustomMutator',
4104 'LLVMFuzzerCustomCrossOver',
4105 'LLVMFuzzerMutate',
4106 ]
4107
4108 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4109
4110 def FilterFile(affected_file):
4111 """Ignore libFuzzer source code."""
4112 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4113 black_list = r"^third_party[\\/]libFuzzer"
4114
4115 return input_api.FilterSourceFile(
4116 affected_file,
4117 white_list=[white_list],
4118 black_list=[black_list])
4119
4120 files_with_missing_header = []
4121 for f in input_api.AffectedSourceFiles(FilterFile):
4122 contents = input_api.ReadFile(f, 'r')
4123 if REQUIRED_HEADER in contents:
4124 continue
4125
4126 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4127 files_with_missing_header.append(f.LocalPath())
4128
4129 if not files_with_missing_header:
4130 return []
4131
4132 long_text = (
4133 'If you define any of the libFuzzer optional functions (%s), it is '
4134 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4135 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4136 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4137 'to access command line arguments passed to the fuzzer. Instead, prefer '
4138 'static initialization and shared resources as documented in '
4139 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4140 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4141 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4142 )
4143
4144 return [output_api.PresubmitPromptWarning(
4145 message="Missing '%s' in:" % REQUIRED_HEADER,
4146 items=files_with_missing_header,
4147 long_text=long_text)]
4148
4149
Mohamed Heikald048240a2019-11-12 16:57:374150def _CheckNewImagesWarning(input_api, output_api):
4151 """
4152 Warns authors who add images into the repo to make sure their images are
4153 optimized before committing.
4154 """
4155 images_added = False
4156 image_paths = []
4157 errors = []
4158 filter_lambda = lambda x: input_api.FilterSourceFile(
4159 x,
4160 black_list=(('(?i).*test', r'.*\/junit\/')
4161 + input_api.DEFAULT_BLACK_LIST),
4162 white_list=[r'.*\/(drawable|mipmap)' ]
4163 )
4164 for f in input_api.AffectedFiles(
4165 include_deletes=False, file_filter=filter_lambda):
4166 local_path = f.LocalPath().lower()
4167 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4168 images_added = True
4169 image_paths.append(f)
4170 if images_added:
4171 errors.append(output_api.PresubmitPromptWarning(
4172 'It looks like you are trying to commit some images. If these are '
4173 'non-test-only images, please make sure to read and apply the tips in '
4174 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4175 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4176 'FYI only and will not block your CL on the CQ.', image_paths))
4177 return errors
4178
4179
dgnaa68d5e2015-06-10 10:08:224180def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574181 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224182 results = []
dgnaa68d5e2015-06-10 10:08:224183 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174184 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224185 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294186 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064187 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4188 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424189 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184190 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574191 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374192 results.extend(_CheckNewImagesWarning(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574193 return results
4194
4195def _AndroidSpecificOnCommitChecks(input_api, output_api):
4196 """Groups commit checks that target android code."""
4197 results = []
4198 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224199 return results
4200
4201
[email protected]22c9bd72011-03-27 16:47:394202def _CommonChecks(input_api, output_api):
4203 """Checks common to both upload and commit."""
4204 results = []
4205 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384206 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544207 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084208
4209 author = input_api.change.author_email
4210 if author and author not in _KNOWN_ROBOTS:
4211 results.extend(
4212 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4213
[email protected]55459852011-08-10 15:17:194214 results.extend(
[email protected]760deea2013-12-10 19:33:494215 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234216 results.extend(
4217 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544218 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184219 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344220 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524221 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224222 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444223 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594224 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314225 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064226 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124227 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184228 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224229 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304230 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494231 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034232 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494233 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444234 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294235 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274236 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074237 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544238 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444239 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394240 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554241 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044242 results.extend(
4243 input_api.canned_checks.CheckChangeHasNoTabs(
4244 input_api,
4245 output_api,
4246 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404247 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164248 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084249 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244250 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474251 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044252 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054253 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144254 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234255 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434256 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404257 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154258 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174259 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264260 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504261 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364262 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064263 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134264 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434265 results.extend(input_api.RunTests(
4266 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144267 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024268 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514269 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364270 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004271 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244272
Vaclav Brozekcdc7defb2018-03-20 09:54:354273 for f in input_api.AffectedFiles():
4274 path, name = input_api.os_path.split(f.LocalPath())
4275 if name == 'PRESUBMIT.py':
4276 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004277 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4278 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074279 # The PRESUBMIT.py file (and the directory containing it) might
4280 # have been affected by being moved or removed, so only try to
4281 # run the tests if they still exist.
4282 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4283 input_api, output_api, full_path,
4284 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394285 return results
[email protected]1f7b4172010-01-28 01:17:344286
[email protected]b337cb5b2011-01-23 21:24:054287
[email protected]b8079ae4a2012-12-05 19:56:494288def _CheckPatchFiles(input_api, output_api):
4289 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4290 if f.LocalPath().endswith(('.orig', '.rej'))]
4291 if problems:
4292 return [output_api.PresubmitError(
4293 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034294 else:
4295 return []
[email protected]b8079ae4a2012-12-05 19:56:494296
4297
Kent Tamura5a8755d2017-06-29 23:37:074298def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214299 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4300 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4301 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074302 include_re = input_api.re.compile(
4303 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4304 extension_re = input_api.re.compile(r'\.[a-z]+$')
4305 errors = []
4306 for f in input_api.AffectedFiles():
4307 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4308 continue
4309 found_line_number = None
4310 found_macro = None
4311 for line_num, line in f.ChangedContents():
4312 match = macro_re.search(line)
4313 if match:
4314 found_line_number = line_num
4315 found_macro = match.group(2)
4316 break
4317 if not found_line_number:
4318 continue
4319
4320 found_include = False
4321 for line in f.NewContents():
4322 if include_re.search(line):
4323 found_include = True
4324 break
4325 if found_include:
4326 continue
4327
4328 if not f.LocalPath().endswith('.h'):
4329 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4330 try:
4331 content = input_api.ReadFile(primary_header_path, 'r')
4332 if include_re.search(content):
4333 continue
4334 except IOError:
4335 pass
4336 errors.append('%s:%d %s macro is used without including build/'
4337 'build_config.h.'
4338 % (f.LocalPath(), found_line_number, found_macro))
4339 if errors:
4340 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4341 return []
4342
4343
[email protected]b00342e7f2013-03-26 16:21:544344def _DidYouMeanOSMacro(bad_macro):
4345 try:
4346 return {'A': 'OS_ANDROID',
4347 'B': 'OS_BSD',
4348 'C': 'OS_CHROMEOS',
4349 'F': 'OS_FREEBSD',
4350 'L': 'OS_LINUX',
4351 'M': 'OS_MACOSX',
4352 'N': 'OS_NACL',
4353 'O': 'OS_OPENBSD',
4354 'P': 'OS_POSIX',
4355 'S': 'OS_SOLARIS',
4356 'W': 'OS_WIN'}[bad_macro[3].upper()]
4357 except KeyError:
4358 return ''
4359
4360
4361def _CheckForInvalidOSMacrosInFile(input_api, f):
4362 """Check for sensible looking, totally invalid OS macros."""
4363 preprocessor_statement = input_api.re.compile(r'^\s*#')
4364 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4365 results = []
4366 for lnum, line in f.ChangedContents():
4367 if preprocessor_statement.search(line):
4368 for match in os_macro.finditer(line):
4369 if not match.group(1) in _VALID_OS_MACROS:
4370 good = _DidYouMeanOSMacro(match.group(1))
4371 did_you_mean = ' (did you mean %s?)' % good if good else ''
4372 results.append(' %s:%d %s%s' % (f.LocalPath(),
4373 lnum,
4374 match.group(1),
4375 did_you_mean))
4376 return results
4377
4378
4379def _CheckForInvalidOSMacros(input_api, output_api):
4380 """Check all affected files for invalid OS macros."""
4381 bad_macros = []
tzik3f295992018-12-04 20:32:234382 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474383 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544384 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4385
4386 if not bad_macros:
4387 return []
4388
4389 return [output_api.PresubmitError(
4390 'Possibly invalid OS macro[s] found. Please fix your code\n'
4391 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4392
lliabraa35bab3932014-10-01 12:16:444393
4394def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4395 """Check all affected files for invalid "if defined" macros."""
4396 ALWAYS_DEFINED_MACROS = (
4397 "TARGET_CPU_PPC",
4398 "TARGET_CPU_PPC64",
4399 "TARGET_CPU_68K",
4400 "TARGET_CPU_X86",
4401 "TARGET_CPU_ARM",
4402 "TARGET_CPU_MIPS",
4403 "TARGET_CPU_SPARC",
4404 "TARGET_CPU_ALPHA",
4405 "TARGET_IPHONE_SIMULATOR",
4406 "TARGET_OS_EMBEDDED",
4407 "TARGET_OS_IPHONE",
4408 "TARGET_OS_MAC",
4409 "TARGET_OS_UNIX",
4410 "TARGET_OS_WIN32",
4411 )
4412 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4413 results = []
4414 for lnum, line in f.ChangedContents():
4415 for match in ifdef_macro.finditer(line):
4416 if match.group(1) in ALWAYS_DEFINED_MACROS:
4417 always_defined = ' %s is always defined. ' % match.group(1)
4418 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4419 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4420 lnum,
4421 always_defined,
4422 did_you_mean))
4423 return results
4424
4425
4426def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4427 """Check all affected files for invalid "if defined" macros."""
4428 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054429 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444430 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054431 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214432 continue
lliabraa35bab3932014-10-01 12:16:444433 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4434 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4435
4436 if not bad_macros:
4437 return []
4438
4439 return [output_api.PresubmitError(
4440 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4441 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4442 bad_macros)]
4443
4444
mlamouria82272622014-09-16 18:45:044445def _CheckForIPCRules(input_api, output_api):
4446 """Check for same IPC rules described in
4447 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4448 """
4449 base_pattern = r'IPC_ENUM_TRAITS\('
4450 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4451 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4452
4453 problems = []
4454 for f in input_api.AffectedSourceFiles(None):
4455 local_path = f.LocalPath()
4456 if not local_path.endswith('.h'):
4457 continue
4458 for line_number, line in f.ChangedContents():
4459 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4460 problems.append(
4461 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4462
4463 if problems:
4464 return [output_api.PresubmitPromptWarning(
4465 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4466 else:
4467 return []
4468
[email protected]b00342e7f2013-03-26 16:21:544469
Stephen Martinis97a394142018-06-07 23:06:054470def _CheckForLongPathnames(input_api, output_api):
4471 """Check to make sure no files being submitted have long paths.
4472 This causes issues on Windows.
4473 """
4474 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194475 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054476 local_path = f.LocalPath()
4477 # Windows has a path limit of 260 characters. Limit path length to 200 so
4478 # that we have some extra for the prefix on dev machines and the bots.
4479 if len(local_path) > 200:
4480 problems.append(local_path)
4481
4482 if problems:
4483 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4484 else:
4485 return []
4486
4487
Daniel Bratell8ba52722018-03-02 16:06:144488def _CheckForIncludeGuards(input_api, output_api):
4489 """Check that header files have proper guards against multiple inclusion.
4490 If a file should not have such guards (and it probably should) then it
4491 should include the string "no-include-guard-because-multiply-included".
4492 """
Daniel Bratell6a75baef62018-06-04 10:04:454493 def is_chromium_header_file(f):
4494 # We only check header files under the control of the Chromium
4495 # project. That is, those outside third_party apart from
4496 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324497 # We also exclude *_message_generator.h headers as they use
4498 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454499 file_with_path = input_api.os_path.normpath(f.LocalPath())
4500 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324501 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454502 (not file_with_path.startswith('third_party') or
4503 file_with_path.startswith(
4504 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144505
4506 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344507 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144508
4509 errors = []
4510
Daniel Bratell6a75baef62018-06-04 10:04:454511 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144512 guard_name = None
4513 guard_line_number = None
4514 seen_guard_end = False
4515
4516 file_with_path = input_api.os_path.normpath(f.LocalPath())
4517 base_file_name = input_api.os_path.splitext(
4518 input_api.os_path.basename(file_with_path))[0]
4519 upper_base_file_name = base_file_name.upper()
4520
4521 expected_guard = replace_special_with_underscore(
4522 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144523
4524 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574525 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4526 # are too many (1000+) files with slight deviations from the
4527 # coding style. The most important part is that the include guard
4528 # is there, and that it's unique, not the name so this check is
4529 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144530 #
4531 # As code becomes more uniform, this could be made stricter.
4532
4533 guard_name_pattern_list = [
4534 # Anything with the right suffix (maybe with an extra _).
4535 r'\w+_H__?',
4536
Daniel Bratell39b5b062018-05-16 18:09:574537 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144538 r'\w+_h',
4539
4540 # Anything including the uppercase name of the file.
4541 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4542 upper_base_file_name)) + r'\w*',
4543 ]
4544 guard_name_pattern = '|'.join(guard_name_pattern_list)
4545 guard_pattern = input_api.re.compile(
4546 r'#ifndef\s+(' + guard_name_pattern + ')')
4547
4548 for line_number, line in enumerate(f.NewContents()):
4549 if 'no-include-guard-because-multiply-included' in line:
4550 guard_name = 'DUMMY' # To not trigger check outside the loop.
4551 break
4552
4553 if guard_name is None:
4554 match = guard_pattern.match(line)
4555 if match:
4556 guard_name = match.group(1)
4557 guard_line_number = line_number
4558
Daniel Bratell39b5b062018-05-16 18:09:574559 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454560 # don't match the chromium style guide, but new files should
4561 # get it right.
4562 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574563 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144564 errors.append(output_api.PresubmitPromptWarning(
4565 'Header using the wrong include guard name %s' % guard_name,
4566 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574567 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144568 else:
4569 # The line after #ifndef should have a #define of the same name.
4570 if line_number == guard_line_number + 1:
4571 expected_line = '#define %s' % guard_name
4572 if line != expected_line:
4573 errors.append(output_api.PresubmitPromptWarning(
4574 'Missing "%s" for include guard' % expected_line,
4575 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4576 'Expected: %r\nGot: %r' % (expected_line, line)))
4577
4578 if not seen_guard_end and line == '#endif // %s' % guard_name:
4579 seen_guard_end = True
4580 elif seen_guard_end:
4581 if line.strip() != '':
4582 errors.append(output_api.PresubmitPromptWarning(
4583 'Include guard %s not covering the whole file' % (
4584 guard_name), [f.LocalPath()]))
4585 break # Nothing else to check and enough to warn once.
4586
4587 if guard_name is None:
4588 errors.append(output_api.PresubmitPromptWarning(
4589 'Missing include guard %s' % expected_guard,
4590 [f.LocalPath()],
4591 'Missing include guard in %s\n'
4592 'Recommended name: %s\n'
4593 'This check can be disabled by having the string\n'
4594 'no-include-guard-because-multiply-included in the header.' %
4595 (f.LocalPath(), expected_guard)))
4596
4597 return errors
4598
4599
mostynbb639aca52015-01-07 20:31:234600def _CheckForWindowsLineEndings(input_api, output_api):
4601 """Check source code and known ascii text files for Windows style line
4602 endings.
4603 """
earthdok1b5e0ee2015-03-10 15:19:104604 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234605
4606 file_inclusion_pattern = (
4607 known_text_files,
4608 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4609 )
4610
mostynbb639aca52015-01-07 20:31:234611 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534612 source_file_filter = lambda f: input_api.FilterSourceFile(
4613 f, white_list=file_inclusion_pattern, black_list=None)
4614 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504615 include_file = False
4616 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234617 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504618 include_file = True
4619 if include_file:
4620 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234621
4622 if problems:
4623 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4624 'these files to contain Windows style line endings?\n' +
4625 '\n'.join(problems))]
4626
4627 return []
4628
4629
Vaclav Brozekd5de76a2018-03-17 07:57:504630def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134631 """Checks that all source files use SYSLOG properly."""
4632 syslog_files = []
4633 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564634 for line_number, line in f.ChangedContents():
4635 if 'SYSLOG' in line:
4636 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4637
pastarmovj89f7ee12016-09-20 14:58:134638 if syslog_files:
4639 return [output_api.PresubmitPromptWarning(
4640 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4641 ' calls.\nFiles to check:\n', items=syslog_files)]
4642 return []
4643
4644
[email protected]1f7b4172010-01-28 01:17:344645def CheckChangeOnUpload(input_api, output_api):
4646 results = []
4647 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474648 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284649 results.extend(
jam93a6ee792017-02-08 23:59:224650 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194651 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224652 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134653 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164654 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534655 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194656 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274657 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544658 return results
[email protected]ca8d1982009-02-19 16:33:124659
4660
[email protected]1bfb8322014-04-23 01:02:414661def GetTryServerMasterForBot(bot):
4662 """Returns the Try Server master for the given bot.
4663
[email protected]0bb112362014-07-26 04:38:324664 It tries to guess the master from the bot name, but may still fail
4665 and return None. There is no longer a default master.
4666 """
4667 # Potentially ambiguous bot names are listed explicitly.
4668 master_map = {
tandriie5587792016-07-14 00:34:504669 'chromium_presubmit': 'master.tryserver.chromium.linux',
4670 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414671 }
[email protected]0bb112362014-07-26 04:38:324672 master = master_map.get(bot)
4673 if not master:
wnwen4fbaab82016-05-25 12:54:364674 if 'android' in bot:
tandriie5587792016-07-14 00:34:504675 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364676 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504677 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324678 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504679 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324680 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504681 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324682 return master
[email protected]1bfb8322014-04-23 01:02:414683
4684
[email protected]ca8d1982009-02-19 16:33:124685def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544686 results = []
[email protected]1f7b4172010-01-28 01:17:344687 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574688 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544689 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274690 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344691 input_api,
4692 output_api,
[email protected]2fdd1f362013-01-16 03:56:034693 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274694
jam93a6ee792017-02-08 23:59:224695 results.extend(
4696 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544697 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4698 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384699 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4700 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414701 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4702 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544703 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144704
4705
4706def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acerad8fb082019-11-19 04:24:214707 PART_FILE_TAG = "part"
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144708 import os
4709 import sys
4710 from io import StringIO
4711
4712 try:
4713 old_sys_path = sys.path
4714 sys.path = sys.path + [input_api.os_path.join(
Mustafa Emre Acerad8fb082019-11-19 04:24:214715 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4716 import grit.grd_reader
4717 import grit.node.message
4718 import grit.util
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144719 finally:
4720 sys.path = old_sys_path
4721
Mustafa Emre Acerad8fb082019-11-19 04:24:214722 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4723 """Load the grd file and return a dict of message ids to messages.
4724
4725 Ignores any nested grdp files pointed by <part> tag.
4726 """
4727 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4728 stop_after=None, first_ids_file=None,
4729 debug=False, defines={'_chromium': 1},
4730 tags_to_ignore=set([PART_FILE_TAG]))
4731 return {
4732 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4733 grit.node.message.MessageNode)
4734 }
4735
4736 def _GetGrdpMessagesFromString(grdp_string):
4737 """Parses the contents of a grdp file given in grdp_string.
4738
4739 grd_reader can't parse grdp files directly. Instead, this creates a
4740 temporary directory with a grd file pointing to the grdp file, and loads the
4741 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4742 """
4743 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4744 <grit latest_public_release="1" current_release="1">
4745 <release seq="1">
4746 <messages>
4747 <part file="sub.grdp" />
4748 </messages>
4749 </release>
4750 </grit>
4751 """
4752 with grit.util.TempDir({'main.grd': WRAPPER,
4753 'sub.grdp': grdp_string}) as temp_dir:
4754 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4755
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144756 new_or_added_paths = set(f.LocalPath()
4757 for f in input_api.AffectedFiles()
4758 if (f.Action() == 'A' or f.Action() == 'M'))
4759 removed_paths = set(f.LocalPath()
4760 for f in input_api.AffectedFiles(include_deletes=True)
4761 if f.Action() == 'D')
4762
4763 affected_grds = [f for f in input_api.AffectedFiles()
4764 if (f.LocalPath().endswith('.grd') or
4765 f.LocalPath().endswith('.grdp'))]
4766 affected_png_paths = [f.AbsoluteLocalPath()
4767 for f in input_api.AffectedFiles()
4768 if (f.LocalPath().endswith('.png'))]
4769
4770 # Check for screenshots. Developers can upload screenshots using
4771 # tools/translation/upload_screenshots.py which finds and uploads
4772 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4773 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4774 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4775 #
4776 # The logic here is as follows:
4777 #
4778 # - If the CL has a .png file under the screenshots directory for a grd
4779 # file, warn the developer. Actual images should never be checked into the
4780 # Chrome repo.
4781 #
4782 # - If the CL contains modified or new messages in grd files and doesn't
4783 # contain the corresponding .sha1 files, warn the developer to add images
4784 # and upload them via tools/translation/upload_screenshots.py.
4785 #
4786 # - If the CL contains modified or new messages in grd files and the
4787 # corresponding .sha1 files, everything looks good.
4788 #
4789 # - If the CL contains removed messages in grd files but the corresponding
4790 # .sha1 files aren't removed, warn the developer to remove them.
4791 unnecessary_screenshots = []
4792 missing_sha1 = []
4793 unnecessary_sha1_files = []
4794
4795
4796 def _CheckScreenshotAdded(screenshots_dir, message_id):
4797 sha1_path = input_api.os_path.join(
4798 screenshots_dir, message_id + '.png.sha1')
4799 if sha1_path not in new_or_added_paths:
4800 missing_sha1.append(sha1_path)
4801
4802
4803 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4804 sha1_path = input_api.os_path.join(
4805 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034806 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144807 unnecessary_sha1_files.append(sha1_path)
4808
4809
4810 for f in affected_grds:
4811 file_path = f.LocalPath()
4812 old_id_to_msg_map = {}
4813 new_id_to_msg_map = {}
4814 if file_path.endswith('.grdp'):
4815 if f.OldContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214816 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394817 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144818 if f.NewContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214819 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394820 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144821 else:
4822 if f.OldContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214823 old_id_to_msg_map = _GetGrdMessages(
4824 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144825 if f.NewContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214826 new_id_to_msg_map = _GetGrdMessages(
4827 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144828
4829 # Compute added, removed and modified message IDs.
4830 old_ids = set(old_id_to_msg_map)
4831 new_ids = set(new_id_to_msg_map)
4832 added_ids = new_ids - old_ids
4833 removed_ids = old_ids - new_ids
4834 modified_ids = set([])
4835 for key in old_ids.intersection(new_ids):
4836 if (old_id_to_msg_map[key].FormatXml()
4837 != new_id_to_msg_map[key].FormatXml()):
4838 modified_ids.add(key)
4839
4840 grd_name, ext = input_api.os_path.splitext(
4841 input_api.os_path.basename(file_path))
4842 screenshots_dir = input_api.os_path.join(
4843 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4844
4845 # Check the screenshot directory for .png files. Warn if there is any.
4846 for png_path in affected_png_paths:
4847 if png_path.startswith(screenshots_dir):
4848 unnecessary_screenshots.append(png_path)
4849
4850 for added_id in added_ids:
4851 _CheckScreenshotAdded(screenshots_dir, added_id)
4852
4853 for modified_id in modified_ids:
4854 _CheckScreenshotAdded(screenshots_dir, modified_id)
4855
4856 for removed_id in removed_ids:
4857 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4858
4859 results = []
4860 if unnecessary_screenshots:
4861 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394862 'Do not include actual screenshots in the changelist. Run '
4863 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144864 sorted(unnecessary_screenshots)))
4865
4866 if missing_sha1:
4867 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394868 'You are adding or modifying UI strings.\n'
4869 'To ensure the best translations, take screenshots of the relevant UI '
4870 '(https://g.co/chrome/translation) and add these files to your '
4871 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144872
4873 if unnecessary_sha1_files:
4874 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394875 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144876 sorted(unnecessary_sha1_files)))
4877
4878 return results