blob: d5642051cfd55ba30a95c821a57bab181d497f4b [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$',
[email protected]06e6d0ff2012-12-11 01:36:4463)
[email protected]ca8d1982009-02-19 16:33:1264
Daniel Bratell609102be2019-03-27 20:53:2165_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1566
[email protected]eea609a2011-11-18 13:10:1267_TEST_ONLY_WARNING = (
68 'You might be calling functions intended only for testing from\n'
69 'production code. It is OK to ignore this warning if you know what\n'
70 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0771 'not perfect. The commit queue will not block on this warning,\n'
72 'however the android-binary-size trybot will block if the method\n'
73 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1274
75
[email protected]cf9b78f2012-11-14 11:40:2876_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4077 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2178 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
79 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2880
wnwenbdc444e2016-05-25 13:44:1581
Daniel Bratell609102be2019-03-27 20:53:2182# Format: Sequence of tuples containing:
83# * String pattern or, if starting with a slash, a regular expression.
84# * Sequence of strings to show when the pattern matches.
85# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:4186_BANNED_JAVA_FUNCTIONS = (
87 (
88 'StrictMode.allowThreadDiskReads()',
89 (
90 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
91 'directly.',
92 ),
93 False,
94 ),
95 (
96 'StrictMode.allowThreadDiskWrites()',
97 (
98 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
99 'directly.',
100 ),
101 False,
102 ),
103)
104
Daniel Bratell609102be2019-03-27 20:53:21105# Format: Sequence of tuples containing:
106# * String pattern or, if starting with a slash, a regular expression.
107# * Sequence of strings to show when the pattern matches.
108# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59109_BANNED_OBJC_FUNCTIONS = (
110 (
111 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20112 (
113 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59114 'prohibited. Please use CrTrackingArea instead.',
115 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
116 ),
117 False,
118 ),
119 (
[email protected]eaae1972014-04-16 04:17:26120 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20121 (
122 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59123 'instead.',
124 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
125 ),
126 False,
127 ),
128 (
129 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59132 'Please use |convertPoint:(point) fromView:nil| instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 True,
136 ),
137 (
138 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20139 (
140 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59141 'Please use |convertPoint:(point) toView:nil| instead.',
142 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
143 ),
144 True,
145 ),
146 (
147 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20148 (
149 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59150 'Please use |convertRect:(point) fromView:nil| instead.',
151 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
152 ),
153 True,
154 ),
155 (
156 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59159 'Please use |convertRect:(point) toView:nil| instead.',
160 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
161 ),
162 True,
163 ),
164 (
165 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59168 'Please use |convertSize:(point) fromView:nil| instead.',
169 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
170 ),
171 True,
172 ),
173 (
174 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20175 (
176 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59177 'Please use |convertSize:(point) toView:nil| instead.',
178 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
179 ),
180 True,
181 ),
jif65398702016-10-27 10:19:48182 (
183 r"/\s+UTF8String\s*]",
184 (
185 'The use of -[NSString UTF8String] is dangerous as it can return null',
186 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
187 'Please use |SysNSStringToUTF8| instead.',
188 ),
189 True,
190 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34191 (
192 r'__unsafe_unretained',
193 (
194 'The use of __unsafe_unretained is almost certainly wrong, unless',
195 'when interacting with NSFastEnumeration or NSInvocation.',
196 'Please use __weak in files build with ARC, nothing otherwise.',
197 ),
198 False,
199 ),
Avi Drissman7382afa02019-04-29 23:27:13200 (
201 'freeWhenDone:NO',
202 (
203 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
204 'Foundation types is prohibited.',
205 ),
206 True,
207 ),
[email protected]127f18ec2012-06-16 05:05:59208)
209
Daniel Bratell609102be2019-03-27 20:53:21210# Format: Sequence of tuples containing:
211# * String pattern or, if starting with a slash, a regular expression.
212# * Sequence of strings to show when the pattern matches.
213# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54214_BANNED_IOS_OBJC_FUNCTIONS = (
215 (
216 r'/\bTEST[(]',
217 (
218 'TEST() macro should not be used in Objective-C++ code as it does not ',
219 'drain the autorelease pool at the end of the test. Use TEST_F() ',
220 'macro instead with a fixture inheriting from PlatformTest (or a ',
221 'typedef).'
222 ),
223 True,
224 ),
225 (
226 r'/\btesting::Test\b',
227 (
228 'testing::Test should not be used in Objective-C++ code as it does ',
229 'not drain the autorelease pool at the end of the test. Use ',
230 'PlatformTest instead.'
231 ),
232 True,
233 ),
234)
235
Peter K. Lee6c03ccff2019-07-15 14:40:05236# Format: Sequence of tuples containing:
237# * String pattern or, if starting with a slash, a regular expression.
238# * Sequence of strings to show when the pattern matches.
239# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
240_BANNED_IOS_EGTEST_FUNCTIONS = (
241 (
242 r'/\bEXPECT_OCMOCK_VERIFY\b',
243 (
244 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
245 'it is meant for GTests. Use [mock verify] instead.'
246 ),
247 True,
248 ),
249)
250
danakj7a2b7082019-05-21 21:13:51251# Directories that contain deprecated Bind() or Callback types.
252# Find sub-directories from a given directory by running:
253# for i in `find . -maxdepth 1 -type d`; do
254# echo "-- $i"
255# (cd $i; git grep -P 'base::(Bind\(|(Callback<|Closure))'|wc -l)
256# done
257#
258# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
259# when they have been converted to modern callback types (OnceCallback,
260# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
261# checks for them and prevent regressions.
262_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
263 '^android_webview/browser/',
264 '^apps/',
265 '^ash/',
danakj7a2b7082019-05-21 21:13:51266 '^base/callback.h', # Intentional.
267 '^chrome/app/',
268 '^chrome/browser/',
269 '^chrome/chrome_elf/',
270 '^chrome/chrome_watcher/',
271 '^chrome/common/',
272 '^chrome/installer/',
273 '^chrome/notification_helper/',
274 '^chrome/renderer/',
275 '^chrome/services/',
276 '^chrome/test/',
277 '^chrome/tools/',
278 '^chrome/utility/',
279 '^chromecast/app/',
280 '^chromecast/browser/',
281 '^chromecast/crash/',
282 '^chromecast/media/',
283 '^chromecast/metrics/',
284 '^chromecast/net/',
285 '^chromeos/attestation/',
286 '^chromeos/audio/',
287 '^chromeos/components/',
288 '^chromeos/cryptohome/',
289 '^chromeos/dbus/',
290 '^chromeos/geolocation/',
291 '^chromeos/login/',
292 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51293 '^chromeos/process_proxy/',
294 '^chromeos/services/',
295 '^chromeos/settings/',
296 '^chromeos/timezone/',
297 '^chromeos/tpm/',
298 '^components/arc/',
299 '^components/assist_ranker/',
300 '^components/autofill/',
301 '^components/autofill_assistant/',
302 '^components/bookmarks/',
303 '^components/browser_sync/',
304 '^components/browser_watcher/',
305 '^components/browsing_data/',
306 '^components/cast_channel/',
307 '^components/certificate_transparency/',
308 '^components/chromeos_camera/',
309 '^components/component_updater/',
310 '^components/content_settings/',
311 '^components/crash/',
312 '^components/cronet/',
313 '^components/data_reduction_proxy/',
314 '^components/discardable_memory/',
315 '^components/dom_distiller/',
316 '^components/domain_reliability/',
317 '^components/download/',
318 '^components/drive/',
319 '^components/exo/',
320 '^components/favicon/',
321 '^components/feature_engagement/',
322 '^components/feedback/',
323 '^components/flags_ui/',
324 '^components/gcm_driver/',
325 '^components/google/',
326 '^components/guest_view/',
327 '^components/heap_profiling/',
328 '^components/history/',
329 '^components/image_fetcher/',
330 '^components/invalidation/',
331 '^components/keyed_service/',
332 '^components/login/',
333 '^components/metrics/',
334 '^components/metrics_services_manager/',
335 '^components/nacl/',
336 '^components/navigation_interception/',
337 '^components/net_log/',
338 '^components/network_time/',
339 '^components/ntp_snippets/',
340 '^components/ntp_tiles/',
341 '^components/offline_items_collection/',
342 '^components/offline_pages/',
343 '^components/omnibox/',
344 '^components/ownership/',
345 '^components/pairing/',
346 '^components/password_manager/',
347 '^components/payments/',
348 '^components/plugins/',
349 '^components/policy/',
350 '^components/pref_registry/',
351 '^components/prefs/',
danakj7a2b7082019-05-21 21:13:51352 '^components/proxy_config/',
353 '^components/quirks/',
354 '^components/rappor/',
355 '^components/remote_cocoa/',
356 '^components/renderer_context_menu/',
357 '^components/rlz/',
358 '^components/safe_browsing/',
359 '^components/search_engines/',
360 '^components/search_provider_logos/',
361 '^components/security_interstitials/',
362 '^components/security_state/',
363 '^components/services/',
364 '^components/sessions/',
365 '^components/signin/',
366 '^components/ssl_errors/',
367 '^components/storage_monitor/',
368 '^components/subresource_filter/',
369 '^components/suggestions/',
370 '^components/supervised_user_error_page/',
371 '^components/sync/',
372 '^components/sync_bookmarks/',
373 '^components/sync_device_info/',
374 '^components/sync_preferences/',
375 '^components/sync_sessions/',
376 '^components/test/',
377 '^components/tracing/',
378 '^components/translate/',
379 '^components/ukm/',
380 '^components/update_client/',
381 '^components/upload_list/',
382 '^components/variations/',
383 '^components/visitedlink/',
384 '^components/web_cache/',
danakj7a2b7082019-05-21 21:13:51385 '^components/webcrypto/',
386 '^components/webdata/',
387 '^components/webdata_services/',
388 '^components/wifi/',
389 '^components/zoom/',
390 '^content/app/',
391 '^content/browser/',
392 '^content/child/',
393 '^content/common/',
394 '^content/public/',
395 '^content/renderer/android/',
396 '^content/renderer/fetchers/',
397 '^content/renderer/image_downloader/',
398 '^content/renderer/input/',
399 '^content/renderer/java/',
400 '^content/renderer/media/',
401 '^content/renderer/media_capture_from_element/',
402 '^content/renderer/media_recorder/',
403 '^content/renderer/p2p/',
404 '^content/renderer/pepper/',
405 '^content/renderer/service_worker/',
406 '^content/renderer/worker/',
407 '^content/test/',
408 '^content/utility/',
409 '^dbus/',
410 '^device/base/',
411 '^device/bluetooth/',
412 '^device/fido/',
413 '^device/gamepad/',
danakj7a2b7082019-05-21 21:13:51414 '^device/vr/',
415 '^extensions/',
416 '^gin/',
417 '^google_apis/dive/',
418 '^google_apis/gaia/',
419 '^google_apis/gcm/',
420 '^headless/',
421 '^ios/chrome/',
422 '^ios/components/',
423 '^ios/net/',
424 '^ios/web/',
425 '^ios/web_view/',
426 '^ipc/',
427 '^media/audio/',
428 '^media/base/',
429 '^media/capture/',
430 '^media/cast/',
431 '^media/cdm/',
432 '^media/device_monitors/',
433 '^media/ffmpeg/',
434 '^media/filters/',
435 '^media/formats/',
436 '^media/gpu/',
437 '^media/mojo/',
438 '^media/muxers/',
439 '^media/remoting/',
440 '^media/renderers/',
441 '^media/test/',
442 '^mojo/core/',
443 '^mojo/public/',
444 '^net/',
445 '^ppapi/proxy/',
446 '^ppapi/shared_impl/',
447 '^ppapi/tests/',
448 '^ppapi/thunk/',
449 '^remoting/base/',
450 '^remoting/client/',
451 '^remoting/codec/',
452 '^remoting/host/',
453 '^remoting/internal/',
454 '^remoting/ios/',
455 '^remoting/protocol/',
456 '^remoting/signaling/',
457 '^remoting/test/',
458 '^sandbox/linux/',
459 '^sandbox/win/',
460 '^services/',
461 '^storage/browser/',
462 '^testing/gmock_mutant.h',
463 '^testing/libfuzzer/',
464 '^third_party/blink/',
465 '^third_party/crashpad/crashpad/test/gtest_main.cc',
466 '^third_party/leveldatabase/leveldb_chrome.cc',
467 '^third_party/boringssl/gtest_main_chromium.cc',
468 '^third_party/cacheinvalidation/overrides/' +
469 'google/cacheinvalidation/deps/callback.h',
470 '^third_party/libaddressinput/chromium/chrome_address_validator.cc',
471 '^third_party/zlib/google/',
472 '^tools/android/',
473 '^tools/clang/base_bind_rewriters/', # Intentional.
474 '^tools/gdb/gdb_chrome.py', # Intentional.
475 '^ui/accelerated_widget_mac/',
476 '^ui/android/',
477 '^ui/aura/',
478 '^ui/base/',
479 '^ui/compositor/',
480 '^ui/display/',
481 '^ui/events/',
482 '^ui/gfx/',
483 '^ui/message_center/',
danakj7a2b7082019-05-21 21:13:51484 '^ui/snapshot/',
485 '^ui/views_content_client/',
486 '^ui/wm/',
487))
[email protected]127f18ec2012-06-16 05:05:59488
Daniel Bratell609102be2019-03-27 20:53:21489# Format: Sequence of tuples containing:
490# * String pattern or, if starting with a slash, a regular expression.
491# * Sequence of strings to show when the pattern matches.
492# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
493# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59494_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20495 (
Dave Tapuska98199b612019-07-10 13:30:44496 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53497 (
498 'New code should not use NULL. Use nullptr instead.',
499 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20500 False,
thomasandersone7caaa9b2017-03-29 19:22:53501 (),
502 ),
Peter Kasting94a56c42019-10-25 21:54:04503 (
504 r'/\busing namespace ',
505 (
506 'Using directives ("using namespace x") are banned by the Google Style',
507 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
508 'Explicitly qualify symbols or use using declarations ("using x::foo").',
509 ),
510 True,
511 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
512 ),
Antonio Gomes07300d02019-03-13 20:59:57513 # Make sure that gtest's FRIEND_TEST() macro is not used; the
514 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
515 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53516 (
[email protected]23e6cbc2012-06-16 18:51:20517 'FRIEND_TEST(',
518 (
[email protected]e3c945502012-06-26 20:01:49519 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20520 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
521 ),
522 False,
[email protected]7345da02012-11-27 14:31:49523 (),
[email protected]23e6cbc2012-06-16 18:51:20524 ),
525 (
Dave Tapuska98199b612019-07-10 13:30:44526 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53527 (
528 'Chrome clients wishing to select events on X windows should use',
529 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
530 'you are selecting events from the GPU process, or if you are using',
531 'an XDisplay other than gfx::GetXDisplay().',
532 ),
533 True,
534 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40535 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04536 r"^ui[\\/]gl[\\/].*\.cc$",
537 r"^media[\\/]gpu[\\/].*\.cc$",
538 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53539 ),
540 ),
541 (
Dave Tapuska98199b612019-07-10 13:30:44542 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20543 (
thomasanderson11aa41d2017-06-08 22:22:38544 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20545 ),
546 True,
547 (
Egor Paskoce145c42018-09-28 19:31:04548 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
549 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
550 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20551 ),
552 ),
553 (
tomhudsone2c14d552016-05-26 17:07:46554 'setMatrixClip',
555 (
556 'Overriding setMatrixClip() is prohibited; ',
557 'the base function is deprecated. ',
558 ),
559 True,
560 (),
561 ),
562 (
[email protected]52657f62013-05-20 05:30:31563 'SkRefPtr',
564 (
565 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22566 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31567 ),
568 True,
569 (),
570 ),
571 (
572 'SkAutoRef',
573 (
574 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22575 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31576 ),
577 True,
578 (),
579 ),
580 (
581 'SkAutoTUnref',
582 (
583 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22584 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31585 ),
586 True,
587 (),
588 ),
589 (
590 'SkAutoUnref',
591 (
592 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
593 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22594 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31595 ),
596 True,
597 (),
598 ),
[email protected]d89eec82013-12-03 14:10:59599 (
600 r'/HANDLE_EINTR\(.*close',
601 (
602 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
603 'descriptor will be closed, and it is incorrect to retry the close.',
604 'Either call close directly and ignore its return value, or wrap close',
605 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
606 ),
607 True,
608 (),
609 ),
610 (
611 r'/IGNORE_EINTR\((?!.*close)',
612 (
613 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
614 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
615 ),
616 True,
617 (
618 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04619 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
620 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59621 ),
622 ),
[email protected]ec5b3f02014-04-04 18:43:43623 (
624 r'/v8::Extension\(',
625 (
626 'Do not introduce new v8::Extensions into the code base, use',
627 'gin::Wrappable instead. See http://crbug.com/334679',
628 ),
629 True,
[email protected]f55c90ee62014-04-12 00:50:03630 (
Egor Paskoce145c42018-09-28 19:31:04631 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03632 ),
[email protected]ec5b3f02014-04-04 18:43:43633 ),
skyostilf9469f72015-04-20 10:38:52634 (
jame2d1a952016-04-02 00:27:10635 '#pragma comment(lib,',
636 (
637 'Specify libraries to link with in build files and not in the source.',
638 ),
639 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41640 (
tzik3f295992018-12-04 20:32:23641 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04642 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41643 ),
jame2d1a952016-04-02 00:27:10644 ),
fdorayc4ac18d2017-05-01 21:39:59645 (
Gabriel Charette7cc6c432018-04-25 20:52:02646 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59647 (
648 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
649 ),
650 False,
651 (),
652 ),
653 (
Gabriel Charette7cc6c432018-04-25 20:52:02654 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59655 (
656 'Consider using THREAD_CHECKER macros instead of the class directly.',
657 ),
658 False,
659 (),
660 ),
dbeamb6f4fde2017-06-15 04:03:06661 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06662 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
663 (
664 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
665 'deprecated (http://crbug.com/634507). Please avoid converting away',
666 'from the Time types in Chromium code, especially if any math is',
667 'being done on time values. For interfacing with platform/library',
668 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
669 'type converter methods instead. For faking TimeXXX values (for unit',
670 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
671 'other use cases, please contact base/time/OWNERS.',
672 ),
673 False,
674 (),
675 ),
676 (
dbeamb6f4fde2017-06-15 04:03:06677 'CallJavascriptFunctionUnsafe',
678 (
679 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
680 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
681 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
682 ),
683 False,
684 (
Egor Paskoce145c42018-09-28 19:31:04685 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
686 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
687 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06688 ),
689 ),
dskiba1474c2bfd62017-07-20 02:19:24690 (
691 'leveldb::DB::Open',
692 (
693 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
694 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
695 "Chrome's tracing, making their memory usage visible.",
696 ),
697 True,
698 (
699 r'^third_party/leveldatabase/.*\.(cc|h)$',
700 ),
Gabriel Charette0592c3a2017-07-26 12:02:04701 ),
702 (
Chris Mumfordc38afb62017-10-09 17:55:08703 'leveldb::NewMemEnv',
704 (
705 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58706 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
707 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08708 ),
709 True,
710 (
711 r'^third_party/leveldatabase/.*\.(cc|h)$',
712 ),
713 ),
714 (
Gabriel Charetted9839bc2017-07-29 14:17:47715 'RunLoop::QuitCurrent',
716 (
Robert Liao64b7ab22017-08-04 23:03:43717 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
718 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47719 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41720 False,
Gabriel Charetted9839bc2017-07-29 14:17:47721 (),
Gabriel Charettea44975052017-08-21 23:14:04722 ),
723 (
724 'base::ScopedMockTimeMessageLoopTaskRunner',
725 (
Gabriel Charette87cc1af2018-04-25 20:52:51726 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11727 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51728 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
729 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
730 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04731 ),
Gabriel Charette87cc1af2018-04-25 20:52:51732 False,
Gabriel Charettea44975052017-08-21 23:14:04733 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57734 ),
735 (
Dave Tapuska98199b612019-07-10 13:30:44736 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57737 (
738 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02739 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57740 ),
741 True,
742 (),
Francois Doray43670e32017-09-27 12:40:38743 ),
744 (
Peter Kasting991618a62019-06-17 22:00:09745 r'/\bstd::stoi\b',
746 (
747 'std::stoi uses exceptions to communicate results. ',
748 'Use base::StringToInt() instead.',
749 ),
750 True,
751 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
752 ),
753 (
754 r'/\bstd::stol\b',
755 (
756 'std::stol uses exceptions to communicate results. ',
757 'Use base::StringToInt() instead.',
758 ),
759 True,
760 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
761 ),
762 (
763 r'/\bstd::stoul\b',
764 (
765 'std::stoul uses exceptions to communicate results. ',
766 'Use base::StringToUint() instead.',
767 ),
768 True,
769 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
770 ),
771 (
772 r'/\bstd::stoll\b',
773 (
774 'std::stoll uses exceptions to communicate results. ',
775 'Use base::StringToInt64() instead.',
776 ),
777 True,
778 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
779 ),
780 (
781 r'/\bstd::stoull\b',
782 (
783 'std::stoull uses exceptions to communicate results. ',
784 'Use base::StringToUint64() instead.',
785 ),
786 True,
787 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
788 ),
789 (
790 r'/\bstd::stof\b',
791 (
792 'std::stof uses exceptions to communicate results. ',
793 'For locale-independent values, e.g. reading numbers from disk',
794 'profiles, use base::StringToDouble().',
795 'For user-visible values, parse using ICU.',
796 ),
797 True,
798 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
799 ),
800 (
801 r'/\bstd::stod\b',
802 (
803 'std::stod uses exceptions to communicate results. ',
804 'For locale-independent values, e.g. reading numbers from disk',
805 'profiles, use base::StringToDouble().',
806 'For user-visible values, parse using ICU.',
807 ),
808 True,
809 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
810 ),
811 (
812 r'/\bstd::stold\b',
813 (
814 'std::stold uses exceptions to communicate results. ',
815 'For locale-independent values, e.g. reading numbers from disk',
816 'profiles, use base::StringToDouble().',
817 'For user-visible values, parse using ICU.',
818 ),
819 True,
820 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
821 ),
822 (
Daniel Bratell69334cc2019-03-26 11:07:45823 r'/\bstd::to_string\b',
824 (
825 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09826 'For locale-independent strings, e.g. writing numbers to disk',
827 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45828 'For user-visible strings, use base::FormatNumber() and',
829 'the related functions in base/i18n/number_formatting.h.',
830 ),
Peter Kasting991618a62019-06-17 22:00:09831 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21832 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45833 ),
834 (
835 r'/\bstd::shared_ptr\b',
836 (
837 'std::shared_ptr should not be used. Use scoped_refptr instead.',
838 ),
839 True,
Daniel Bratell609102be2019-03-27 20:53:21840 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
841 ),
842 (
Peter Kasting991618a62019-06-17 22:00:09843 r'/\bstd::weak_ptr\b',
844 (
845 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
846 ),
847 True,
848 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
849 ),
850 (
Daniel Bratell609102be2019-03-27 20:53:21851 r'/\blong long\b',
852 (
853 'long long is banned. Use stdint.h if you need a 64 bit number.',
854 ),
855 False, # Only a warning since it is already used.
856 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
857 ),
858 (
859 r'/\bstd::bind\b',
860 (
861 'std::bind is banned because of lifetime risks.',
862 'Use base::BindOnce or base::BindRepeating instead.',
863 ),
864 True,
865 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
866 ),
867 (
868 r'/\b#include <chrono>\b',
869 (
870 '<chrono> overlaps with Time APIs in base. Keep using',
871 'base classes.',
872 ),
873 True,
874 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
875 ),
876 (
877 r'/\b#include <exception>\b',
878 (
879 'Exceptions are banned and disabled in Chromium.',
880 ),
881 True,
882 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
883 ),
884 (
885 r'/\bstd::function\b',
886 (
887 'std::function is banned. Instead use base::Callback which directly',
888 'supports Chromium\'s weak pointers, ref counting and more.',
889 ),
Peter Kasting991618a62019-06-17 22:00:09890 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21891 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
892 ),
893 (
894 r'/\b#include <random>\b',
895 (
896 'Do not use any random number engines from <random>. Instead',
897 'use base::RandomBitGenerator.',
898 ),
899 True,
900 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
901 ),
902 (
903 r'/\bstd::ratio\b',
904 (
905 'std::ratio is banned by the Google Style Guide.',
906 ),
907 True,
908 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45909 ),
910 (
Francois Doray43670e32017-09-27 12:40:38911 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
912 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
913 (
914 'Use the new API in base/threading/thread_restrictions.h.',
915 ),
Gabriel Charette04b138f2018-08-06 00:03:22916 False,
Francois Doray43670e32017-09-27 12:40:38917 (),
918 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38919 (
danakj7a2b7082019-05-21 21:13:51920 r'/\bbase::Bind\(',
921 (
922 'Please use base::Bind{Once,Repeating} instead',
923 'of base::Bind. (crbug.com/714018)',
924 ),
925 False,
926 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
927 ),
928 (
929 r'/\bbase::Callback[<:]',
930 (
931 'Please use base::{Once,Repeating}Callback instead',
932 'of base::Callback. (crbug.com/714018)',
933 ),
934 False,
935 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
936 ),
937 (
938 r'/\bbase::Closure\b',
939 (
940 'Please use base::{Once,Repeating}Closure instead',
941 'of base::Closure. (crbug.com/714018)',
942 ),
943 False,
944 _NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,
945 ),
946 (
Alex Ilin5929abe32019-04-03 17:09:34947 r'/base::SharedMemory(|Handle)',
Alex Ilin63058f62019-03-28 19:29:45948 (
949 'base::SharedMemory is deprecated. Please use',
950 '{Writable,ReadOnly}SharedMemoryRegion instead.',
951 ),
952 False,
953 (),
954 ),
955 (
Michael Giuffrida7f93d6922019-04-19 14:39:58956 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19957 (
958 'RunMessageLoop is deprecated, use RunLoop instead.',
959 ),
960 False,
961 (),
962 ),
963 (
Dave Tapuska98199b612019-07-10 13:30:44964 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19965 (
966 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
967 ),
968 False,
969 (),
970 ),
971 (
Dave Tapuska98199b612019-07-10 13:30:44972 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19973 (
974 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
975 "if you're convinced you need this.",
976 ),
977 False,
978 (),
979 ),
980 (
Dave Tapuska98199b612019-07-10 13:30:44981 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19982 (
983 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04984 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19985 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
986 'async events instead of flushing threads.',
987 ),
988 False,
989 (),
990 ),
991 (
992 r'MessageLoopRunner',
993 (
994 'MessageLoopRunner is deprecated, use RunLoop instead.',
995 ),
996 False,
997 (),
998 ),
999 (
Dave Tapuska98199b612019-07-10 13:30:441000 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:191001 (
1002 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
1003 "gab@ if you found a use case where this is the only solution.",
1004 ),
1005 False,
1006 (),
1007 ),
1008 (
Victor Costane48a2e82019-03-15 22:02:341009 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:161010 (
Victor Costane48a2e82019-03-15 22:02:341011 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:161012 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
1013 ),
1014 True,
1015 (
1016 r'^sql/initialization\.(cc|h)$',
1017 r'^third_party/sqlite/.*\.(c|cc|h)$',
1018 ),
1019 ),
Matt Menke7f520a82018-03-28 21:38:371020 (
1021 'net::URLFetcher',
1022 (
1023 'net::URLFetcher should no longer be used in content embedders. ',
1024 'Instead, use network::SimpleURLLoader instead, which supports ',
1025 'an out-of-process network stack. ',
1026 'net::URLFetcher may still be used in binaries that do not embed',
1027 'content.',
1028 ),
Matt Menke59716d02018-04-05 12:45:531029 False,
Matt Menke7f520a82018-03-28 21:38:371030 (
Egor Paskoce145c42018-09-28 19:31:041031 r'^ios[\\/].*\.(cc|h)$',
1032 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:371033 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:041034 r'^net[\\/].*\.(cc|h)$',
1035 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:431036 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:371037 ),
1038 ),
jdoerried7d10ab2018-04-27 10:46:131039 (
Dave Tapuska98199b612019-07-10 13:30:441040 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:471041 (
1042 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
1043 'base::RandomShuffle instead.'
1044 ),
1045 True,
1046 (),
1047 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:241048 (
1049 'ios/web/public/test/http_server',
1050 (
1051 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
1052 ),
1053 False,
1054 (),
1055 ),
Robert Liao764c9492019-01-24 18:46:281056 (
1057 'GetAddressOf',
1058 (
1059 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:461060 'implicated in a few leaks. Use operator& instead. See ',
1061 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:281062 ),
1063 True,
1064 (),
1065 ),
Antonio Gomes07300d02019-03-13 20:59:571066 (
1067 'DEFINE_TYPE_CASTS',
1068 (
1069 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1070 '//third_party/blink/renderer/platform/casting.h.'
1071 ),
1072 True,
1073 (
1074 r'^third_party/blink/renderer/.*\.(cc|h)$',
1075 ),
1076 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381077 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:451078 r'/\bIsHTML.+Element\(\b',
1079 (
1080 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1081 ' helpers IsA<HTMLXXXXElement> from ',
1082 '//third_party/blink/renderer/platform/casting.h.'
1083 ),
1084 False,
1085 (
1086 r'^third_party/blink/renderer/.*\.(cc|h)$',
1087 ),
1088 ),
1089 (
1090 r'/\bToHTML.+Element(|OrNull)\(\b',
1091 (
1092 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1093 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1094 'and DynamicTo<HTMLXXXXElement> from ',
1095 '//third_party/blink/renderer/platform/casting.h.'
1096 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1097 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1098 ),
1099 False,
1100 (
1101 r'^third_party/blink/renderer/.*\.(cc|h)$',
1102 ),
1103 ),
1104 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371105 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381106 (
1107 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1108 ),
1109 True,
1110 (),
1111 ),
Ben Lewisa9514602019-04-29 17:53:051112 (
1113 'SHFileOperation',
1114 (
1115 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1116 'complex functions to achieve the same goals. Use IFileOperation for ',
1117 'any esoteric actions instead.'
1118 ),
1119 True,
1120 (),
1121 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181122 (
Cliff Smolinsky81951642019-04-30 21:39:511123 'StringFromGUID2',
1124 (
1125 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1126 'Use base::win::String16FromGUID instead.'
1127 ),
1128 True,
1129 (
1130 r'/base/win/win_util_unittest.cc'
1131 ),
1132 ),
1133 (
1134 'StringFromCLSID',
1135 (
1136 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1137 'Use base::win::String16FromGUID instead.'
1138 ),
1139 True,
1140 (
1141 r'/base/win/win_util_unittest.cc'
1142 ),
1143 ),
1144 (
Avi Drissman7382afa02019-04-29 23:27:131145 'kCFAllocatorNull',
1146 (
1147 'The use of kCFAllocatorNull with the NoCopy creation of ',
1148 'CoreFoundation types is prohibited.',
1149 ),
1150 True,
1151 (),
1152 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291153 (
1154 'mojo::ConvertTo',
1155 (
1156 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1157 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1158 'StringTraits if you would like to convert between custom types and',
1159 'the wire format of mojom types.'
1160 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221161 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291162 (
Wezf89dec092019-09-11 19:38:331163 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1164 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291165 r'^third_party/blink/.*\.(cc|h)$',
1166 r'^content/renderer/.*\.(cc|h)$',
1167 ),
1168 ),
[email protected]127f18ec2012-06-16 05:05:591169)
1170
Mario Sanchez Prada2472cab2019-09-18 10:58:311171# Format: Sequence of tuples containing:
1172# * String pattern or, if starting with a slash, a regular expression.
1173# * Sequence of strings to show when the pattern matches.
1174_DEPRECATED_MOJO_TYPES = (
1175 (
1176 r'/\bmojo::AssociatedBinding\b',
1177 (
1178 'mojo::AssociatedBinding<Interface> is deprecated.',
1179 'Use mojo::AssociatedReceiver<Interface> instead.',
1180 ),
1181 ),
1182 (
1183 r'/\bmojo::AssociatedBindingSet\b',
1184 (
1185 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1186 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1187 ),
1188 ),
1189 (
1190 r'/\bmojo::AssociatedInterfacePtr\b',
1191 (
1192 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1193 'Use mojo::AssociatedRemote<Interface> instead.',
1194 ),
1195 ),
1196 (
1197 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1198 (
1199 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1200 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1201 ),
1202 ),
1203 (
1204 r'/\bmojo::AssociatedInterfaceRequest\b',
1205 (
1206 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1207 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1208 ),
1209 ),
1210 (
1211 r'/\bmojo::Binding\b',
1212 (
1213 'mojo::Binding<Interface> is deprecated.',
1214 'Use mojo::Receiver<Interface> instead.',
1215 ),
1216 ),
1217 (
1218 r'/\bmojo::BindingSet\b',
1219 (
1220 'mojo::BindingSet<Interface> is deprecated.',
1221 'Use mojo::ReceiverSet<Interface> instead.',
1222 ),
1223 ),
1224 (
1225 r'/\bmojo::InterfacePtr\b',
1226 (
1227 'mojo::InterfacePtr<Interface> is deprecated.',
1228 'Use mojo::Remote<Interface> instead.',
1229 ),
1230 ),
1231 (
1232 r'/\bmojo::InterfacePtrInfo\b',
1233 (
1234 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1235 'Use mojo::PendingRemote<Interface> instead.',
1236 ),
1237 ),
1238 (
1239 r'/\bmojo::InterfaceRequest\b',
1240 (
1241 'mojo::InterfaceRequest<Interface> is deprecated.',
1242 'Use mojo::PendingReceiver<Interface> instead.',
1243 ),
1244 ),
1245 (
1246 r'/\bmojo::MakeRequest\b',
1247 (
1248 'mojo::MakeRequest is deprecated.',
1249 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1250 ),
1251 ),
1252 (
1253 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1254 (
1255 'mojo::MakeRequest is deprecated.',
1256 'Use mojo::AssociatedRemote::'
1257 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1258 ),
1259 ),
1260 (
1261 r'/\bmojo::MakeStrongBinding\b',
1262 (
1263 'mojo::MakeStrongBinding is deprecated.',
1264 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1265 'mojo::MakeSelfOwnedReceiver() instead.',
1266 ),
1267 ),
1268 (
1269 r'/\bmojo::MakeStrongAssociatedBinding\b',
1270 (
1271 'mojo::MakeStrongAssociatedBinding is deprecated.',
1272 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1273 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1274 ),
1275 ),
1276 (
1277 r'/\bmojo::StrongAssociatedBindingSet\b',
1278 (
1279 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1280 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1281 ),
1282 ),
1283 (
1284 r'/\bmojo::StrongBindingSet\b',
1285 (
1286 'mojo::StrongBindingSet<Interface> is deprecated.',
1287 'Use mojo::UniqueReceiverSet<Interface> instead.',
1288 ),
1289 ),
1290)
wnwenbdc444e2016-05-25 13:44:151291
mlamouria82272622014-09-16 18:45:041292_IPC_ENUM_TRAITS_DEPRECATED = (
1293 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501294 'See http://www.chromium.org/Home/chromium-security/education/'
1295 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041296
Stephen Martinis97a394142018-06-07 23:06:051297_LONG_PATH_ERROR = (
1298 'Some files included in this CL have file names that are too long (> 200'
1299 ' characters). If committed, these files will cause issues on Windows. See'
1300 ' https://crbug.com/612667 for more details.'
1301)
1302
Shenghua Zhangbfaa38b82017-11-16 21:58:021303_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041304 r".*[\\/]BuildHooksAndroidImpl\.java",
1305 r".*[\\/]LicenseContentProvider\.java",
1306 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281307 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021308]
[email protected]127f18ec2012-06-16 05:05:591309
Sean Kau46e29bc2017-08-28 16:31:161310# These paths contain test data and other known invalid JSON files.
1311_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041312 r'test[\\/]data[\\/]',
1313 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1314 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041315 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431316 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161317]
1318
1319
[email protected]b00342e7f2013-03-26 16:21:541320_VALID_OS_MACROS = (
1321 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081322 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541323 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121324 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541325 'OS_BSD',
1326 'OS_CAT', # For testing.
1327 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041328 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541329 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371330 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541331 'OS_IOS',
1332 'OS_LINUX',
1333 'OS_MACOSX',
1334 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211335 'OS_NACL_NONSFI',
1336 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121337 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541338 'OS_OPENBSD',
1339 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371340 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541341 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541342 'OS_WIN',
1343)
1344
1345
agrievef32bcc72016-04-04 14:57:401346_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391347 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361348 'base/android/jni_generator/jni_generator.pydeps',
1349 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221350 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361351 'build/android/gyp/aar.pydeps',
1352 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271353 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361354 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381355 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361356 'build/android/gyp/bytecode_processor.pydeps',
1357 'build/android/gyp/compile_resources.pydeps',
Tibor Goldschwendt84ec04c2019-08-23 21:19:091358 'build/android/gyp/create_app_bundle_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361359 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1360 'build/android/gyp/copy_ex.pydeps',
1361 'build/android/gyp/create_app_bundle.pydeps',
1362 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361363 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221364 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361365 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591366 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361367 'build/android/gyp/dex.pydeps',
1368 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361369 'build/android/gyp/filter_zip.pydeps',
1370 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361371 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361372 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581373 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361374 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261375 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361376 'build/android/gyp/javac.pydeps',
1377 'build/android/gyp/jinja_template.pydeps',
1378 'build/android/gyp/lint.pydeps',
1379 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361380 'build/android/gyp/merge_manifest.pydeps',
1381 'build/android/gyp/prepare_resources.pydeps',
1382 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241383 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361384 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461385 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561386 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361387 'build/android/incremental_install/generate_android_manifest.pydeps',
1388 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221389 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401390 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041391 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361392 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411393 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051394 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191395 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431396 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021397 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401398]
1399
wnwenbdc444e2016-05-25 13:44:151400
agrievef32bcc72016-04-04 14:57:401401_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421402 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131403 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421404 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1405 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131406 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
John Budorickbc3571aa2019-04-25 02:20:061407 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221408 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401409]
1410
wnwenbdc444e2016-05-25 13:44:151411
agrievef32bcc72016-04-04 14:57:401412_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1413
1414
Eric Boren6fd2b932018-01-25 15:05:081415# Bypass the AUTHORS check for these accounts.
1416_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291417 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1418 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081419 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321420 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591421 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451422 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591423 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221424 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041425 ) | set('%[email protected]' % s
1426 for s in ('chromium-autoroll',)
1427 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301428 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081429
1430
Daniel Bratell65b033262019-04-23 08:17:061431def _IsCPlusPlusFile(input_api, file_path):
1432 """Returns True if this file contains C++-like code (and not Python,
1433 Go, Java, MarkDown, ...)"""
1434
1435 ext = input_api.os_path.splitext(file_path)[1]
1436 # This list is compatible with CppChecker.IsCppFile but we should
1437 # consider adding ".c" to it. If we do that we can use this function
1438 # at more places in the code.
1439 return ext in (
1440 '.h',
1441 '.cc',
1442 '.cpp',
1443 '.m',
1444 '.mm',
1445 )
1446
1447def _IsCPlusPlusHeaderFile(input_api, file_path):
1448 return input_api.os_path.splitext(file_path)[1] == ".h"
1449
1450
1451def _IsJavaFile(input_api, file_path):
1452 return input_api.os_path.splitext(file_path)[1] == ".java"
1453
1454
1455def _IsProtoFile(input_api, file_path):
1456 return input_api.os_path.splitext(file_path)[1] == ".proto"
1457
[email protected]55459852011-08-10 15:17:191458def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1459 """Attempts to prevent use of functions intended only for testing in
1460 non-testing code. For now this is just a best-effort implementation
1461 that ignores header files and may have some false positives. A
1462 better implementation would probably need a proper C++ parser.
1463 """
1464 # We only scan .cc files and the like, as the declaration of
1465 # for-testing functions in header files are hard to distinguish from
1466 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491467 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191468
jochenc0d4808c2015-07-27 09:25:421469 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191470 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091471 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191472 exclusion_pattern = input_api.re.compile(
1473 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1474 base_function_pattern, base_function_pattern))
1475
1476 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441477 black_list = (_EXCLUDED_PATHS +
1478 _TEST_CODE_EXCLUDED_PATHS +
1479 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191480 return input_api.FilterSourceFile(
1481 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491482 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191483 black_list=black_list)
1484
1485 problems = []
1486 for f in input_api.AffectedSourceFiles(FilterFile):
1487 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241488 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031489 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461490 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031491 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191492 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031493 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191494
1495 if problems:
[email protected]f7051d52013-04-02 18:31:421496 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031497 else:
1498 return []
[email protected]55459852011-08-10 15:17:191499
1500
Vaclav Brozek7dbc28c2018-03-27 08:35:231501def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1502 """This is a simplified version of
1503 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1504 """
1505 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1506 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1507 name_pattern = r'ForTest(s|ing)?'
1508 # Describes an occurrence of "ForTest*" inside a // comment.
1509 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1510 # Catch calls.
1511 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1512 # Ignore definitions. (Comments are ignored separately.)
1513 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1514
1515 problems = []
1516 sources = lambda x: input_api.FilterSourceFile(
1517 x,
1518 black_list=(('(?i).*test', r'.*\/junit\/')
1519 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491520 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231521 )
1522 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1523 local_path = f.LocalPath()
1524 is_inside_javadoc = False
1525 for line_number, line in f.ChangedContents():
1526 if is_inside_javadoc and javadoc_end_re.search(line):
1527 is_inside_javadoc = False
1528 if not is_inside_javadoc and javadoc_start_re.search(line):
1529 is_inside_javadoc = True
1530 if is_inside_javadoc:
1531 continue
1532 if (inclusion_re.search(line) and
1533 not comment_re.search(line) and
1534 not exclusion_re.search(line)):
1535 problems.append(
1536 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1537
1538 if problems:
1539 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1540 else:
1541 return []
1542
1543
[email protected]10689ca2011-09-02 02:31:541544def _CheckNoIOStreamInHeaders(input_api, output_api):
1545 """Checks to make sure no .h files include <iostream>."""
1546 files = []
1547 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1548 input_api.re.MULTILINE)
1549 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1550 if not f.LocalPath().endswith('.h'):
1551 continue
1552 contents = input_api.ReadFile(f)
1553 if pattern.search(contents):
1554 files.append(f)
1555
1556 if len(files):
yolandyandaabc6d2016-04-18 18:29:391557 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061558 'Do not #include <iostream> in header files, since it inserts static '
1559 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541560 '#include <ostream>. See http://crbug.com/94794',
1561 files) ]
1562 return []
1563
Danil Chapovalov3518f362018-08-11 16:13:431564def _CheckNoStrCatRedefines(input_api, output_api):
1565 """Checks no windows headers with StrCat redefined are included directly."""
1566 files = []
1567 pattern_deny = input_api.re.compile(
1568 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1569 input_api.re.MULTILINE)
1570 pattern_allow = input_api.re.compile(
1571 r'^#include\s"base/win/windows_defines.inc"',
1572 input_api.re.MULTILINE)
1573 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1574 contents = input_api.ReadFile(f)
1575 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1576 files.append(f.LocalPath())
1577
1578 if len(files):
1579 return [output_api.PresubmitError(
1580 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1581 'directly since they pollute code with StrCat macro. Instead, '
1582 'include matching header from base/win. See http://crbug.com/856536',
1583 files) ]
1584 return []
1585
[email protected]10689ca2011-09-02 02:31:541586
[email protected]72df4e782012-06-21 16:28:181587def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521588 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181589 problems = []
1590 for f in input_api.AffectedFiles():
1591 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1592 continue
1593
1594 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041595 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181596 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1597
1598 if not problems:
1599 return []
1600 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1601 '\n'.join(problems))]
1602
Dominic Battre033531052018-09-24 15:45:341603def _CheckNoDISABLETypoInTests(input_api, output_api):
1604 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1605
1606 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1607 instead of DISABLED_. To filter false positives, reports are only generated
1608 if a corresponding MAYBE_ line exists.
1609 """
1610 problems = []
1611
1612 # The following two patterns are looked for in tandem - is a test labeled
1613 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1614 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1615 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1616
1617 # This is for the case that a test is disabled on all platforms.
1618 full_disable_pattern = input_api.re.compile(
1619 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1620 input_api.re.MULTILINE)
1621
Katie Df13948e2018-09-25 07:33:441622 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341623 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1624 continue
1625
1626 # Search for MABYE_, DISABLE_ pairs.
1627 disable_lines = {} # Maps of test name to line number.
1628 maybe_lines = {}
1629 for line_num, line in f.ChangedContents():
1630 disable_match = disable_pattern.search(line)
1631 if disable_match:
1632 disable_lines[disable_match.group(1)] = line_num
1633 maybe_match = maybe_pattern.search(line)
1634 if maybe_match:
1635 maybe_lines[maybe_match.group(1)] = line_num
1636
1637 # Search for DISABLE_ occurrences within a TEST() macro.
1638 disable_tests = set(disable_lines.keys())
1639 maybe_tests = set(maybe_lines.keys())
1640 for test in disable_tests.intersection(maybe_tests):
1641 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1642
1643 contents = input_api.ReadFile(f)
1644 full_disable_match = full_disable_pattern.search(contents)
1645 if full_disable_match:
1646 problems.append(' %s' % f.LocalPath())
1647
1648 if not problems:
1649 return []
1650 return [
1651 output_api.PresubmitPromptWarning(
1652 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1653 '\n'.join(problems))
1654 ]
1655
[email protected]72df4e782012-06-21 16:28:181656
danakj61c1aa22015-10-26 19:55:521657def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571658 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521659 errors = []
1660 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1661 input_api.re.MULTILINE)
1662 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1663 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1664 continue
1665 for lnum, line in f.ChangedContents():
1666 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171667 errors.append(output_api.PresubmitError(
1668 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571669 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171670 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521671 return errors
1672
1673
Makoto Shimazu3ad422cd2019-05-08 02:35:141674def _FindHistogramNameInChunk(histogram_name, chunk):
1675 """Tries to find a histogram name or prefix in a line.
1676
1677 Returns the existence of the histogram name, or None if it needs more chunk
1678 to determine."""
mcasasb7440c282015-02-04 14:52:191679 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1680 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141681 if '<affected-histogram' in chunk:
1682 # If the tag is not completed, needs more chunk to get the name.
1683 if not '>' in chunk:
1684 return None
1685 if not 'name="' in chunk:
1686 return False
1687 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1688 # expect the only attribute is the name.
1689 histogram_prefix = chunk.split('"')[1]
1690 return histogram_prefix in histogram_name
1691 # Typically the whole histogram name should in the line.
1692 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191693
1694
1695def _CheckUmaHistogramChanges(input_api, output_api):
1696 """Check that UMA histogram names in touched lines can still be found in other
1697 lines of the patch or in histograms.xml. Note that this check would not catch
1698 the reverse: changes in histograms.xml not matched in the code itself."""
1699 touched_histograms = []
1700 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471701 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1702 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1703 name_pattern = r'"(.*?)"'
1704 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1705 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1706 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1707 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1708 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171709 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191710 for f in input_api.AffectedFiles():
1711 # If histograms.xml itself is modified, keep the modified lines for later.
1712 if f.LocalPath().endswith(('histograms.xml')):
1713 histograms_xml_modifications = f.ChangedContents()
1714 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471715 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1716 single_line_re = single_line_c_re
1717 split_line_prefix_re = split_line_c_prefix_re
1718 elif f.LocalPath().endswith(('java')):
1719 single_line_re = single_line_java_re
1720 split_line_prefix_re = split_line_java_prefix_re
1721 else:
mcasasb7440c282015-02-04 14:52:191722 continue
1723 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171724 if last_line_matched_prefix:
1725 suffix_found = split_line_suffix_re.search(line)
1726 if suffix_found :
1727 touched_histograms.append([suffix_found.group(1), f, line_num])
1728 last_line_matched_prefix = False
1729 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061730 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191731 if found:
1732 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171733 continue
1734 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191735
1736 # Search for the touched histogram names in the local modifications to
1737 # histograms.xml, and, if not found, on the base histograms.xml file.
1738 unmatched_histograms = []
1739 for histogram_info in touched_histograms:
1740 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141741 chunk = ''
mcasasb7440c282015-02-04 14:52:191742 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141743 chunk += line
1744 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1745 if histogram_name_found is None:
1746 continue
1747 chunk = ''
mcasasb7440c282015-02-04 14:52:191748 if histogram_name_found:
1749 break
1750 if not histogram_name_found:
1751 unmatched_histograms.append(histogram_info)
1752
eromanb90c82e7e32015-04-01 15:13:491753 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191754 problems = []
1755 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491756 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191757 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451758 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191759 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141760 chunk = ''
mcasasb7440c282015-02-04 14:52:191761 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141762 chunk += line
1763 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1764 chunk)
1765 if histogram_name_found is None:
1766 continue
1767 chunk = ''
mcasasb7440c282015-02-04 14:52:191768 if histogram_name_found:
1769 break
1770 if not histogram_name_found:
1771 problems.append(' [%s:%d] %s' %
1772 (f.LocalPath(), line_num, histogram_name))
1773
1774 if not problems:
1775 return []
1776 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1777 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491778 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191779
wnwenbdc444e2016-05-25 13:44:151780
yolandyandaabc6d2016-04-18 18:29:391781def _CheckFlakyTestUsage(input_api, output_api):
1782 """Check that FlakyTest annotation is our own instead of the android one"""
1783 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1784 files = []
1785 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1786 if f.LocalPath().endswith('Test.java'):
1787 if pattern.search(input_api.ReadFile(f)):
1788 files.append(f)
1789 if len(files):
1790 return [output_api.PresubmitError(
1791 'Use org.chromium.base.test.util.FlakyTest instead of '
1792 'android.test.FlakyTest',
1793 files)]
1794 return []
mcasasb7440c282015-02-04 14:52:191795
wnwenbdc444e2016-05-25 13:44:151796
[email protected]8ea5d4b2011-09-13 21:49:221797def _CheckNoNewWStrings(input_api, output_api):
1798 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271799 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221800 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201801 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571802 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341803 '/win/' in f.LocalPath() or
1804 'chrome_elf' in f.LocalPath() or
1805 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201806 continue
[email protected]8ea5d4b2011-09-13 21:49:221807
[email protected]a11dbe9b2012-08-07 01:32:581808 allowWString = False
[email protected]b5c24292011-11-28 14:38:201809 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581810 if 'presubmit: allow wstring' in line:
1811 allowWString = True
1812 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271813 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581814 allowWString = False
1815 else:
1816 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221817
[email protected]55463aa62011-10-12 00:48:271818 if not problems:
1819 return []
1820 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581821 ' If you are calling a cross-platform API that accepts a wstring, '
1822 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271823 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221824
1825
[email protected]2a8ac9c2011-10-19 17:20:441826def _CheckNoDEPSGIT(input_api, output_api):
1827 """Make sure .DEPS.git is never modified manually."""
1828 if any(f.LocalPath().endswith('.DEPS.git') for f in
1829 input_api.AffectedFiles()):
1830 return [output_api.PresubmitError(
1831 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1832 'automated system based on what\'s in DEPS and your changes will be\n'
1833 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501834 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1835 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441836 'for more information')]
1837 return []
1838
1839
tandriief664692014-09-23 14:51:471840def _CheckValidHostsInDEPS(input_api, output_api):
1841 """Checks that DEPS file deps are from allowed_hosts."""
1842 # Run only if DEPS file has been modified to annoy fewer bystanders.
1843 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1844 return []
1845 # Outsource work to gclient verify
1846 try:
John Budorickf20c0042019-04-25 23:23:401847 gclient_path = input_api.os_path.join(
1848 input_api.PresubmitLocalPath(),
1849 'third_party', 'depot_tools', 'gclient.py')
1850 input_api.subprocess.check_output(
1851 [input_api.python_executable, gclient_path, 'verify'],
1852 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471853 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201854 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471855 return [output_api.PresubmitError(
1856 'DEPS file must have only git dependencies.',
1857 long_text=error.output)]
1858
1859
Mario Sanchez Prada2472cab2019-09-18 10:58:311860def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1861 type_name, message):
1862 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1863
1864 Returns an string composed of the name of the file, the line number where the
1865 match has been found and the additional text passed as |message| in case the
1866 target type name matches the text inside the line passed as parameter.
1867 """
1868 matched = False
1869 if type_name[0:1] == '/':
1870 regex = type_name[1:]
1871 if input_api.re.search(regex, line):
1872 matched = True
1873 elif type_name in line:
1874 matched = True
1875
1876 result = []
1877 if matched:
1878 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1879 for message_line in message:
1880 result.append(' %s' % message_line)
1881
1882 return result
1883
1884
[email protected]127f18ec2012-06-16 05:05:591885def _CheckNoBannedFunctions(input_api, output_api):
1886 """Make sure that banned functions are not used."""
1887 warnings = []
1888 errors = []
1889
wnwenbdc444e2016-05-25 13:44:151890 def IsBlacklisted(affected_file, blacklist):
1891 local_path = affected_file.LocalPath()
1892 for item in blacklist:
1893 if input_api.re.match(item, local_path):
1894 return True
1895 return False
1896
Peter K. Lee6c03ccff2019-07-15 14:40:051897 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541898 local_path = affected_file.LocalPath()
1899 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1900 return False
1901 basename = input_api.os_path.basename(local_path)
1902 if 'ios' in basename.split('_'):
1903 return True
1904 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1905 if sep and 'ios' in local_path.split(sep):
1906 return True
1907 return False
1908
wnwenbdc444e2016-05-25 13:44:151909 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311910 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1911 func_name, message)
1912 if problems:
wnwenbdc444e2016-05-25 13:44:151913 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311914 errors.extend(problems)
1915 else:
1916 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151917
Eric Stevensona9a980972017-09-23 00:04:411918 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1919 for f in input_api.AffectedFiles(file_filter=file_filter):
1920 for line_num, line in f.ChangedContents():
1921 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1922 CheckForMatch(f, line_num, line, func_name, message, error)
1923
[email protected]127f18ec2012-06-16 05:05:591924 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1925 for f in input_api.AffectedFiles(file_filter=file_filter):
1926 for line_num, line in f.ChangedContents():
1927 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151928 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591929
Peter K. Lee6c03ccff2019-07-15 14:40:051930 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541931 for line_num, line in f.ChangedContents():
1932 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1933 CheckForMatch(f, line_num, line, func_name, message, error)
1934
Peter K. Lee6c03ccff2019-07-15 14:40:051935 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1936 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1937 for line_num, line in f.ChangedContents():
1938 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1939 CheckForMatch(f, line_num, line, func_name, message, error)
1940
[email protected]127f18ec2012-06-16 05:05:591941 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1942 for f in input_api.AffectedFiles(file_filter=file_filter):
1943 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491944 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491945 if IsBlacklisted(f, excluded_paths):
1946 continue
wnwenbdc444e2016-05-25 13:44:151947 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591948
1949 result = []
1950 if (warnings):
1951 result.append(output_api.PresubmitPromptWarning(
1952 'Banned functions were used.\n' + '\n'.join(warnings)))
1953 if (errors):
1954 result.append(output_api.PresubmitError(
1955 'Banned functions were used.\n' + '\n'.join(errors)))
1956 return result
1957
1958
Mario Sanchez Prada2472cab2019-09-18 10:58:311959def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1960 """Make sure that old Mojo types are not used."""
1961 warnings = []
1962
1963 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1964 for f in input_api.AffectedFiles(file_filter=file_filter):
1965 # Only need to check Blink for warnings for now.
1966 if not f.LocalPath().startswith('third_party/blink'):
1967 continue
1968
1969 for line_num, line in f.ChangedContents():
1970 for func_name, message in _DEPRECATED_MOJO_TYPES:
1971 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1972 func_name, message)
1973 if problems:
1974 warnings.extend(problems)
1975
1976 result = []
1977 if (warnings):
1978 result.append(output_api.PresubmitPromptWarning(
1979 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
1980 return result
1981
1982
[email protected]6c063c62012-07-11 19:11:061983def _CheckNoPragmaOnce(input_api, output_api):
1984 """Make sure that banned functions are not used."""
1985 files = []
1986 pattern = input_api.re.compile(r'^#pragma\s+once',
1987 input_api.re.MULTILINE)
1988 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1989 if not f.LocalPath().endswith('.h'):
1990 continue
1991 contents = input_api.ReadFile(f)
1992 if pattern.search(contents):
1993 files.append(f)
1994
1995 if files:
1996 return [output_api.PresubmitError(
1997 'Do not use #pragma once in header files.\n'
1998 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1999 files)]
2000 return []
2001
[email protected]127f18ec2012-06-16 05:05:592002
[email protected]e7479052012-09-19 00:26:122003def _CheckNoTrinaryTrueFalse(input_api, output_api):
2004 """Checks to make sure we don't introduce use of foo ? true : false."""
2005 problems = []
2006 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2007 for f in input_api.AffectedFiles():
2008 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2009 continue
2010
2011 for line_num, line in f.ChangedContents():
2012 if pattern.match(line):
2013 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2014
2015 if not problems:
2016 return []
2017 return [output_api.PresubmitPromptWarning(
2018 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2019 '\n'.join(problems))]
2020
2021
[email protected]55f9f382012-07-31 11:02:182022def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282023 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182024 change. Breaking - rules is an error, breaking ! rules is a
2025 warning.
2026 """
mohan.reddyf21db962014-10-16 12:26:472027 import sys
[email protected]55f9f382012-07-31 11:02:182028 # We need to wait until we have an input_api object and use this
2029 # roundabout construct to import checkdeps because this file is
2030 # eval-ed and thus doesn't have __file__.
2031 original_sys_path = sys.path
2032 try:
2033 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472034 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182035 import checkdeps
[email protected]55f9f382012-07-31 11:02:182036 from rules import Rule
2037 finally:
2038 # Restore sys.path to what it was before.
2039 sys.path = original_sys_path
2040
2041 added_includes = []
rhalavati08acd232017-04-03 07:23:282042 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242043 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182044 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062045 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502046 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082047 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062048 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502049 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082050 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062051 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502052 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082053 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182054
[email protected]26385172013-05-09 23:11:352055 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182056
2057 error_descriptions = []
2058 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282059 error_subjects = set()
2060 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182061 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2062 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082063 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182064 description_with_path = '%s\n %s' % (path, rule_description)
2065 if rule_type == Rule.DISALLOW:
2066 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282067 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182068 else:
2069 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282070 warning_subjects.add("#includes")
2071
2072 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2073 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082074 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282075 description_with_path = '%s\n %s' % (path, rule_description)
2076 if rule_type == Rule.DISALLOW:
2077 error_descriptions.append(description_with_path)
2078 error_subjects.add("imports")
2079 else:
2080 warning_descriptions.append(description_with_path)
2081 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182082
Jinsuk Kim5a092672017-10-24 22:42:242083 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022084 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082085 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242086 description_with_path = '%s\n %s' % (path, rule_description)
2087 if rule_type == Rule.DISALLOW:
2088 error_descriptions.append(description_with_path)
2089 error_subjects.add("imports")
2090 else:
2091 warning_descriptions.append(description_with_path)
2092 warning_subjects.add("imports")
2093
[email protected]55f9f382012-07-31 11:02:182094 results = []
2095 if error_descriptions:
2096 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282097 'You added one or more %s that violate checkdeps rules.'
2098 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182099 error_descriptions))
2100 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422101 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282102 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182103 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282104 '%s? See relevant DEPS file(s) for details and contacts.' %
2105 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182106 warning_descriptions))
2107 return results
2108
2109
[email protected]fbcafe5a2012-08-08 15:31:222110def _CheckFilePermissions(input_api, output_api):
2111 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152112 if input_api.platform == 'win32':
2113 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292114 checkperms_tool = input_api.os_path.join(
2115 input_api.PresubmitLocalPath(),
2116 'tools', 'checkperms', 'checkperms.py')
2117 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472118 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392119 with input_api.CreateTemporaryFile() as file_list:
2120 for f in input_api.AffectedFiles():
2121 # checkperms.py file/directory arguments must be relative to the
2122 # repository.
2123 file_list.write(f.LocalPath() + '\n')
2124 file_list.close()
2125 args += ['--file-list', file_list.name]
2126 try:
2127 input_api.subprocess.check_output(args)
2128 return []
2129 except input_api.subprocess.CalledProcessError as error:
2130 return [output_api.PresubmitError(
2131 'checkperms.py failed:',
2132 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222133
2134
robertocn832f5992017-01-04 19:01:302135def _CheckTeamTags(input_api, output_api):
2136 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2137 checkteamtags_tool = input_api.os_path.join(
2138 input_api.PresubmitLocalPath(),
2139 'tools', 'checkteamtags', 'checkteamtags.py')
2140 args = [input_api.python_executable, checkteamtags_tool,
2141 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222142 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302143 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2144 'OWNERS']
2145 try:
2146 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052147 warnings = input_api.subprocess.check_output(args + files).splitlines()
2148 if warnings:
2149 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302150 return []
2151 except input_api.subprocess.CalledProcessError as error:
2152 return [output_api.PresubmitError(
2153 'checkteamtags.py failed:',
2154 long_text=error.output)]
2155
2156
[email protected]c8278b32012-10-30 20:35:492157def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2158 """Makes sure we don't include ui/aura/window_property.h
2159 in header files.
2160 """
2161 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2162 errors = []
2163 for f in input_api.AffectedFiles():
2164 if not f.LocalPath().endswith('.h'):
2165 continue
2166 for line_num, line in f.ChangedContents():
2167 if pattern.match(line):
2168 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2169
2170 results = []
2171 if errors:
2172 results.append(output_api.PresubmitError(
2173 'Header files should not include ui/aura/window_property.h', errors))
2174 return results
2175
2176
[email protected]70ca77752012-11-20 03:45:032177def _CheckForVersionControlConflictsInFile(input_api, f):
2178 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2179 errors = []
2180 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162181 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232182 # First-level headers in markdown look a lot like version control
2183 # conflict markers. http://daringfireball.net/projects/markdown/basics
2184 continue
[email protected]70ca77752012-11-20 03:45:032185 if pattern.match(line):
2186 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2187 return errors
2188
2189
2190def _CheckForVersionControlConflicts(input_api, output_api):
2191 """Usually this is not intentional and will cause a compile failure."""
2192 errors = []
2193 for f in input_api.AffectedFiles():
2194 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2195
2196 results = []
2197 if errors:
2198 results.append(output_api.PresubmitError(
2199 'Version control conflict markers found, please resolve.', errors))
2200 return results
2201
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202202
estadee17314a02017-01-12 16:22:162203def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2204 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2205 errors = []
2206 for f in input_api.AffectedFiles():
2207 for line_num, line in f.ChangedContents():
2208 if pattern.search(line):
2209 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2210
2211 results = []
2212 if errors:
2213 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502214 'Found Google support URL addressed by answer number. Please replace '
2215 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162216 return results
2217
[email protected]70ca77752012-11-20 03:45:032218
[email protected]06e6d0ff2012-12-11 01:36:442219def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2220 def FilterFile(affected_file):
2221 """Filter function for use with input_api.AffectedSourceFiles,
2222 below. This filters out everything except non-test files from
2223 top-level directories that generally speaking should not hard-code
2224 service URLs (e.g. src/android_webview/, src/content/ and others).
2225 """
2226 return input_api.FilterSourceFile(
2227 affected_file,
Egor Paskoce145c42018-09-28 19:31:042228 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442229 black_list=(_EXCLUDED_PATHS +
2230 _TEST_CODE_EXCLUDED_PATHS +
2231 input_api.DEFAULT_BLACK_LIST))
2232
reillyi38965732015-11-16 18:27:332233 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2234 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462235 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2236 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442237 problems = [] # items are (filename, line_number, line)
2238 for f in input_api.AffectedSourceFiles(FilterFile):
2239 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462240 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442241 problems.append((f.LocalPath(), line_num, line))
2242
2243 if problems:
[email protected]f7051d52013-04-02 18:31:422244 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442245 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582246 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442247 [' %s:%d: %s' % (
2248 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032249 else:
2250 return []
[email protected]06e6d0ff2012-12-11 01:36:442251
2252
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492253# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272254def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2255 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312256 The native_client_sdk directory is excluded because it has auto-generated PNG
2257 files for documentation.
[email protected]d2530012013-01-25 16:39:272258 """
[email protected]d2530012013-01-25 16:39:272259 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492260 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042261 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312262 file_filter = lambda f: input_api.FilterSourceFile(
2263 f, white_list=white_list, black_list=black_list)
2264 for f in input_api.AffectedFiles(include_deletes=False,
2265 file_filter=file_filter):
2266 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272267
2268 results = []
2269 if errors:
2270 results.append(output_api.PresubmitError(
2271 'The name of PNG files should not have abbreviations. \n'
2272 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2273 'Contact [email protected] if you have questions.', errors))
2274 return results
2275
2276
Daniel Cheng4dcdb6b2017-04-13 08:30:172277def _ExtractAddRulesFromParsedDeps(parsed_deps):
2278 """Extract the rules that add dependencies from a parsed DEPS file.
2279
2280 Args:
2281 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2282 add_rules = set()
2283 add_rules.update([
2284 rule[1:] for rule in parsed_deps.get('include_rules', [])
2285 if rule.startswith('+') or rule.startswith('!')
2286 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502287 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172288 {}).iteritems():
2289 add_rules.update([
2290 rule[1:] for rule in rules
2291 if rule.startswith('+') or rule.startswith('!')
2292 ])
2293 return add_rules
2294
2295
2296def _ParseDeps(contents):
2297 """Simple helper for parsing DEPS files."""
2298 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172299 class _VarImpl:
2300
2301 def __init__(self, local_scope):
2302 self._local_scope = local_scope
2303
2304 def Lookup(self, var_name):
2305 """Implements the Var syntax."""
2306 try:
2307 return self._local_scope['vars'][var_name]
2308 except KeyError:
2309 raise Exception('Var is not defined: %s' % var_name)
2310
2311 local_scope = {}
2312 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172313 'Var': _VarImpl(local_scope).Lookup,
2314 }
2315 exec contents in global_scope, local_scope
2316 return local_scope
2317
2318
2319def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082320 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412321 a set of DEPS entries that we should look up.
2322
2323 For a directory (rather than a specific filename) we fake a path to
2324 a specific filename by adding /DEPS. This is chosen as a file that
2325 will seldom or never be subject to per-file include_rules.
2326 """
[email protected]2b438d62013-11-14 17:54:142327 # We ignore deps entries on auto-generated directories.
2328 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082329
Daniel Cheng4dcdb6b2017-04-13 08:30:172330 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2331 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2332
2333 added_deps = new_deps.difference(old_deps)
2334
[email protected]2b438d62013-11-14 17:54:142335 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172336 for added_dep in added_deps:
2337 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2338 continue
2339 # Assume that a rule that ends in .h is a rule for a specific file.
2340 if added_dep.endswith('.h'):
2341 results.add(added_dep)
2342 else:
2343 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082344 return results
2345
2346
[email protected]e871964c2013-05-13 14:14:552347def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2348 """When a dependency prefixed with + is added to a DEPS file, we
2349 want to make sure that the change is reviewed by an OWNER of the
2350 target file or directory, to avoid layering violations from being
2351 introduced. This check verifies that this happens.
2352 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172353 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242354
2355 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492356 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242357 for f in input_api.AffectedFiles(include_deletes=False,
2358 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552359 filename = input_api.os_path.basename(f.LocalPath())
2360 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172361 virtual_depended_on_files.update(_CalculateAddedDeps(
2362 input_api.os_path,
2363 '\n'.join(f.OldContents()),
2364 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552365
[email protected]e871964c2013-05-13 14:14:552366 if not virtual_depended_on_files:
2367 return []
2368
2369 if input_api.is_committing:
2370 if input_api.tbr:
2371 return [output_api.PresubmitNotifyResult(
2372 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272373 if input_api.dry_run:
2374 return [output_api.PresubmitNotifyResult(
2375 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552376 if not input_api.change.issue:
2377 return [output_api.PresubmitError(
2378 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402379 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552380 output = output_api.PresubmitError
2381 else:
2382 output = output_api.PresubmitNotifyResult
2383
2384 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502385 owner_email, reviewers = (
2386 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2387 input_api,
2388 owners_db.email_regexp,
2389 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552390
2391 owner_email = owner_email or input_api.change.author_email
2392
[email protected]de4f7d22013-05-23 14:27:462393 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512394 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462395 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552396 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2397 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412398
2399 # We strip the /DEPS part that was added by
2400 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2401 # directory.
2402 def StripDeps(path):
2403 start_deps = path.rfind('/DEPS')
2404 if start_deps != -1:
2405 return path[:start_deps]
2406 else:
2407 return path
2408 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552409 for path in missing_files]
2410
2411 if unapproved_dependencies:
2412 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152413 output('You need LGTM from owners of depends-on paths in DEPS that were '
2414 'modified in this CL:\n %s' %
2415 '\n '.join(sorted(unapproved_dependencies)))]
2416 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2417 output_list.append(output(
2418 'Suggested missing target path OWNERS:\n %s' %
2419 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552420 return output_list
2421
2422 return []
2423
2424
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492425# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402426def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492427 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402428 black_list = (_EXCLUDED_PATHS +
2429 _TEST_CODE_EXCLUDED_PATHS +
2430 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042431 (r"^base[\\/]logging\.h$",
2432 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222433 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042434 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2435 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2436 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122437 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182438 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152439 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032440 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152441 r"^chrome[\\/]chrome_cleaner[\\/].*",
2442 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2443 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042444 r"^chromecast[\\/]",
2445 r"^cloud_print[\\/]",
2446 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482447 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042448 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312449 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042450 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462451 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042452 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462453 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042454 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252455 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042456 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2457 r"^courgette[\\/]courgette_tool\.cc$",
2458 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272459 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002460 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332461 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042462 r"^ipc[\\/]ipc_logging\.cc$",
2463 r"^native_client_sdk[\\/]",
2464 r"^remoting[\\/]base[\\/]logging\.h$",
2465 r"^remoting[\\/]host[\\/].*",
2466 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062467 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332468 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042469 r"^tools[\\/]",
2470 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2471 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332472 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402473 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492474 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402475
thomasanderson625d3932017-03-29 07:16:582476 log_info = set([])
2477 printf = set([])
[email protected]85218562013-11-22 07:41:402478
2479 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582480 for _, line in f.ChangedContents():
2481 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2482 log_info.add(f.LocalPath())
2483 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2484 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372485
thomasanderson625d3932017-03-29 07:16:582486 if input_api.re.search(r"\bprintf\(", line):
2487 printf.add(f.LocalPath())
2488 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2489 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402490
2491 if log_info:
2492 return [output_api.PresubmitError(
2493 'These files spam the console log with LOG(INFO):',
2494 items=log_info)]
2495 if printf:
2496 return [output_api.PresubmitError(
2497 'These files spam the console log with printf/fprintf:',
2498 items=printf)]
2499 return []
2500
2501
[email protected]49aa76a2013-12-04 06:59:162502def _CheckForAnonymousVariables(input_api, output_api):
2503 """These types are all expected to hold locks while in scope and
2504 so should never be anonymous (which causes them to be immediately
2505 destroyed)."""
2506 they_who_must_be_named = [
2507 'base::AutoLock',
2508 'base::AutoReset',
2509 'base::AutoUnlock',
2510 'SkAutoAlphaRestore',
2511 'SkAutoBitmapShaderInstall',
2512 'SkAutoBlitterChoose',
2513 'SkAutoBounderCommit',
2514 'SkAutoCallProc',
2515 'SkAutoCanvasRestore',
2516 'SkAutoCommentBlock',
2517 'SkAutoDescriptor',
2518 'SkAutoDisableDirectionCheck',
2519 'SkAutoDisableOvalCheck',
2520 'SkAutoFree',
2521 'SkAutoGlyphCache',
2522 'SkAutoHDC',
2523 'SkAutoLockColors',
2524 'SkAutoLockPixels',
2525 'SkAutoMalloc',
2526 'SkAutoMaskFreeImage',
2527 'SkAutoMutexAcquire',
2528 'SkAutoPathBoundsUpdate',
2529 'SkAutoPDFRelease',
2530 'SkAutoRasterClipValidate',
2531 'SkAutoRef',
2532 'SkAutoTime',
2533 'SkAutoTrace',
2534 'SkAutoUnref',
2535 ]
2536 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2537 # bad: base::AutoLock(lock.get());
2538 # not bad: base::AutoLock lock(lock.get());
2539 bad_pattern = input_api.re.compile(anonymous)
2540 # good: new base::AutoLock(lock.get())
2541 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2542 errors = []
2543
2544 for f in input_api.AffectedFiles():
2545 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2546 continue
2547 for linenum, line in f.ChangedContents():
2548 if bad_pattern.search(line) and not good_pattern.search(line):
2549 errors.append('%s:%d' % (f.LocalPath(), linenum))
2550
2551 if errors:
2552 return [output_api.PresubmitError(
2553 'These lines create anonymous variables that need to be named:',
2554 items=errors)]
2555 return []
2556
2557
Peter Kasting4844e46e2018-02-23 07:27:102558def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532559 # Returns whether |template_str| is of the form <T, U...> for some types T
2560 # and U. Assumes that |template_str| is already in the form <...>.
2561 def HasMoreThanOneArg(template_str):
2562 # Level of <...> nesting.
2563 nesting = 0
2564 for c in template_str:
2565 if c == '<':
2566 nesting += 1
2567 elif c == '>':
2568 nesting -= 1
2569 elif c == ',' and nesting == 1:
2570 return True
2571 return False
2572
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492573 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102574 sources = lambda affected_file: input_api.FilterSourceFile(
2575 affected_file,
2576 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2577 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492578 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552579
2580 # Pattern to capture a single "<...>" block of template arguments. It can
2581 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2582 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2583 # latter would likely require counting that < and > match, which is not
2584 # expressible in regular languages. Should the need arise, one can introduce
2585 # limited counting (matching up to a total number of nesting depth), which
2586 # should cover all practical cases for already a low nesting limit.
2587 template_arg_pattern = (
2588 r'<[^>]*' # Opening block of <.
2589 r'>([^<]*>)?') # Closing block of >.
2590 # Prefix expressing that whatever follows is not already inside a <...>
2591 # block.
2592 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102593 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552594 not_inside_template_arg_pattern
2595 + r'\bstd::unique_ptr'
2596 + template_arg_pattern
2597 + r'\(\)')
2598
2599 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2600 template_arg_no_array_pattern = (
2601 r'<[^>]*[^]]' # Opening block of <.
2602 r'>([^(<]*[^]]>)?') # Closing block of >.
2603 # Prefix saying that what follows is the start of an expression.
2604 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2605 # Suffix saying that what follows are call parentheses with a non-empty list
2606 # of arguments.
2607 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532608 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552609 return_construct_pattern = input_api.re.compile(
2610 start_of_expr_pattern
2611 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532612 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552613 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532614 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552615 + nonempty_arg_list_pattern)
2616
Vaclav Brozek851d9602018-04-04 16:13:052617 problems_constructor = []
2618 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102619 for f in input_api.AffectedSourceFiles(sources):
2620 for line_number, line in f.ChangedContents():
2621 # Disallow:
2622 # return std::unique_ptr<T>(foo);
2623 # bar = std::unique_ptr<T>(foo);
2624 # But allow:
2625 # return std::unique_ptr<T[]>(foo);
2626 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532627 # And also allow cases when the second template argument is present. Those
2628 # cases cannot be handled by std::make_unique:
2629 # return std::unique_ptr<T, U>(foo);
2630 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052631 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532632 return_construct_result = return_construct_pattern.search(line)
2633 if return_construct_result and not HasMoreThanOneArg(
2634 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052635 problems_constructor.append(
2636 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102637 # Disallow:
2638 # std::unique_ptr<T>()
2639 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052640 problems_nullptr.append(
2641 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2642
2643 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162644 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052645 errors.append(output_api.PresubmitError(
2646 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162647 problems_nullptr))
2648 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052649 errors.append(output_api.PresubmitError(
2650 'The following files use explicit std::unique_ptr constructor.'
2651 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162652 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102653 return errors
2654
2655
[email protected]999261d2014-03-03 20:08:082656def _CheckUserActionUpdate(input_api, output_api):
2657 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522658 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082659 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522660 # If actions.xml is already included in the changelist, the PRESUBMIT
2661 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082662 return []
2663
[email protected]999261d2014-03-03 20:08:082664 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2665 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522666 current_actions = None
[email protected]999261d2014-03-03 20:08:082667 for f in input_api.AffectedFiles(file_filter=file_filter):
2668 for line_num, line in f.ChangedContents():
2669 match = input_api.re.search(action_re, line)
2670 if match:
[email protected]2f92dec2014-03-07 19:21:522671 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2672 # loaded only once.
2673 if not current_actions:
2674 with open('tools/metrics/actions/actions.xml') as actions_f:
2675 current_actions = actions_f.read()
2676 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082677 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522678 action = 'name="{0}"'.format(action_name)
2679 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082680 return [output_api.PresubmitPromptWarning(
2681 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522682 'tools/metrics/actions/actions.xml. Please run '
2683 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082684 % (f.LocalPath(), line_num, action_name))]
2685 return []
2686
2687
Daniel Cheng13ca61a882017-08-25 15:11:252688def _ImportJSONCommentEater(input_api):
2689 import sys
2690 sys.path = sys.path + [input_api.os_path.join(
2691 input_api.PresubmitLocalPath(),
2692 'tools', 'json_comment_eater')]
2693 import json_comment_eater
2694 return json_comment_eater
2695
2696
[email protected]99171a92014-06-03 08:44:472697def _GetJSONParseError(input_api, filename, eat_comments=True):
2698 try:
2699 contents = input_api.ReadFile(filename)
2700 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252701 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132702 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472703
2704 input_api.json.loads(contents)
2705 except ValueError as e:
2706 return e
2707 return None
2708
2709
2710def _GetIDLParseError(input_api, filename):
2711 try:
2712 contents = input_api.ReadFile(filename)
2713 idl_schema = input_api.os_path.join(
2714 input_api.PresubmitLocalPath(),
2715 'tools', 'json_schema_compiler', 'idl_schema.py')
2716 process = input_api.subprocess.Popen(
2717 [input_api.python_executable, idl_schema],
2718 stdin=input_api.subprocess.PIPE,
2719 stdout=input_api.subprocess.PIPE,
2720 stderr=input_api.subprocess.PIPE,
2721 universal_newlines=True)
2722 (_, error) = process.communicate(input=contents)
2723 return error or None
2724 except ValueError as e:
2725 return e
2726
2727
2728def _CheckParseErrors(input_api, output_api):
2729 """Check that IDL and JSON files do not contain syntax errors."""
2730 actions = {
2731 '.idl': _GetIDLParseError,
2732 '.json': _GetJSONParseError,
2733 }
[email protected]99171a92014-06-03 08:44:472734 # Most JSON files are preprocessed and support comments, but these do not.
2735 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042736 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472737 ]
2738 # Only run IDL checker on files in these directories.
2739 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042740 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2741 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472742 ]
2743
2744 def get_action(affected_file):
2745 filename = affected_file.LocalPath()
2746 return actions.get(input_api.os_path.splitext(filename)[1])
2747
[email protected]99171a92014-06-03 08:44:472748 def FilterFile(affected_file):
2749 action = get_action(affected_file)
2750 if not action:
2751 return False
2752 path = affected_file.LocalPath()
2753
Sean Kau46e29bc2017-08-28 16:31:162754 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472755 return False
2756
2757 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162758 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472759 return False
2760 return True
2761
2762 results = []
2763 for affected_file in input_api.AffectedFiles(
2764 file_filter=FilterFile, include_deletes=False):
2765 action = get_action(affected_file)
2766 kwargs = {}
2767 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162768 _MatchesFile(input_api, json_no_comments_patterns,
2769 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472770 kwargs['eat_comments'] = False
2771 parse_error = action(input_api,
2772 affected_file.AbsoluteLocalPath(),
2773 **kwargs)
2774 if parse_error:
2775 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2776 (affected_file.LocalPath(), parse_error)))
2777 return results
2778
2779
[email protected]760deea2013-12-10 19:33:492780def _CheckJavaStyle(input_api, output_api):
2781 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472782 import sys
[email protected]760deea2013-12-10 19:33:492783 original_sys_path = sys.path
2784 try:
2785 sys.path = sys.path + [input_api.os_path.join(
2786 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2787 import checkstyle
2788 finally:
2789 # Restore sys.path to what it was before.
2790 sys.path = original_sys_path
2791
2792 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092793 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512794 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492795
2796
Nate Fischerdfd9812e2019-07-18 22:03:002797def _CheckPythonDevilInit(input_api, output_api):
2798 """Checks to make sure devil is initialized correctly in python scripts."""
2799 script_common_initialize_pattern = input_api.re.compile(
2800 r'script_common\.InitializeEnvironment\(')
2801 devil_env_config_initialize = input_api.re.compile(
2802 r'devil_env\.config\.Initialize\(')
2803
2804 errors = []
2805
2806 sources = lambda affected_file: input_api.FilterSourceFile(
2807 affected_file,
2808 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2809 (r'^build[\\/]android[\\/]devil_chromium\.py',
2810 r'^third_party[\\/].*',)),
2811 white_list=[r'.*\.py$'])
2812
2813 for f in input_api.AffectedSourceFiles(sources):
2814 for line_num, line in f.ChangedContents():
2815 if (script_common_initialize_pattern.search(line) or
2816 devil_env_config_initialize.search(line)):
2817 errors.append("%s:%d" % (f.LocalPath(), line_num))
2818
2819 results = []
2820
2821 if errors:
2822 results.append(output_api.PresubmitError(
2823 'Devil initialization should always be done using '
2824 'devil_chromium.Initialize() in the chromium project, to use better '
2825 'defaults for dependencies (ex. up-to-date version of adb).',
2826 errors))
2827
2828 return results
2829
2830
Sean Kau46e29bc2017-08-28 16:31:162831def _MatchesFile(input_api, patterns, path):
2832 for pattern in patterns:
2833 if input_api.re.search(pattern, path):
2834 return True
2835 return False
2836
2837
Daniel Cheng7052cdf2017-11-21 19:23:292838def _GetOwnersFilesToCheckForIpcOwners(input_api):
2839 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172840
Daniel Cheng7052cdf2017-11-21 19:23:292841 Returns:
2842 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2843 contain to cover IPC-related files with noparent reviewer rules.
2844 """
2845 # Whether or not a file affects IPC is (mostly) determined by a simple list
2846 # of filename patterns.
dchenge07de812016-06-20 19:27:172847 file_patterns = [
palmerb19a0932017-01-24 04:00:312848 # Legacy IPC:
dchenge07de812016-06-20 19:27:172849 '*_messages.cc',
2850 '*_messages*.h',
2851 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312852 # Mojo IPC:
dchenge07de812016-06-20 19:27:172853 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472854 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172855 '*_struct_traits*.*',
2856 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312857 '*.typemap',
2858 # Android native IPC:
2859 '*.aidl',
2860 # Blink uses a different file naming convention:
2861 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472862 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172863 '*StructTraits*.*',
2864 '*TypeConverter*.*',
2865 ]
2866
scottmg7a6ed5ba2016-11-04 18:22:042867 # These third_party directories do not contain IPCs, but contain files
2868 # matching the above patterns, which trigger false positives.
2869 exclude_paths = [
2870 'third_party/crashpad/*',
Andres Medinae684cf42018-08-27 18:48:232871 'third_party/protobuf/benchmarks/python/*',
Daniel Chengebe635e2018-07-13 12:36:062872 'third_party/third_party/blink/renderer/platform/bindings/*',
Nico Weberee3dc9b2017-08-31 17:09:292873 'third_party/win_build_output/*',
Clark DuVallfb37334c2019-09-03 18:32:172874 # These aidl files are just used to communicate between class loaders
2875 # running in the same process.
2876 'weblayer/browser/java/org/chromium/weblayer_private/aidl/*',
scottmg7a6ed5ba2016-11-04 18:22:042877 ]
2878
dchenge07de812016-06-20 19:27:172879 # Dictionary mapping an OWNERS file path to Patterns.
2880 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2881 # rules ) to a PatternEntry.
2882 # PatternEntry is a dictionary with two keys:
2883 # - 'files': the files that are matched by this pattern
2884 # - 'rules': the per-file rules needed for this pattern
2885 # For example, if we expect OWNERS file to contain rules for *.mojom and
2886 # *_struct_traits*.*, Patterns might look like this:
2887 # {
2888 # '*.mojom': {
2889 # 'files': ...,
2890 # 'rules': [
2891 # 'per-file *.mojom=set noparent',
2892 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2893 # ],
2894 # },
2895 # '*_struct_traits*.*': {
2896 # 'files': ...,
2897 # 'rules': [
2898 # 'per-file *_struct_traits*.*=set noparent',
2899 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2900 # ],
2901 # },
2902 # }
2903 to_check = {}
2904
Daniel Cheng13ca61a882017-08-25 15:11:252905 def AddPatternToCheck(input_file, pattern):
2906 owners_file = input_api.os_path.join(
2907 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2908 if owners_file not in to_check:
2909 to_check[owners_file] = {}
2910 if pattern not in to_check[owners_file]:
2911 to_check[owners_file][pattern] = {
2912 'files': [],
2913 'rules': [
2914 'per-file %s=set noparent' % pattern,
2915 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2916 ]
2917 }
Vaclav Brozekd5de76a2018-03-17 07:57:502918 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252919
dchenge07de812016-06-20 19:27:172920 # Iterate through the affected files to see what we actually need to check
2921 # for. We should only nag patch authors about per-file rules if a file in that
2922 # directory would match that pattern. If a directory only contains *.mojom
2923 # files and no *_messages*.h files, we should only nag about rules for
2924 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252925 for f in input_api.AffectedFiles(include_deletes=False):
2926 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362927 # affected files for .json, .cc, and .h files which look like they contain
2928 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162929 if (f.LocalPath().endswith('.json') and
2930 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2931 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252932 json_comment_eater = _ImportJSONCommentEater(input_api)
2933 mostly_json_lines = '\n'.join(f.NewContents())
2934 # Comments aren't allowed in strict JSON, so filter them out.
2935 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432936 try:
2937 json_content = input_api.json.loads(json_lines)
2938 except:
2939 # There's another PRESUBMIT check that already verifies that JSON files
2940 # are not invalid, so no need to emit another warning here.
2941 continue
Daniel Cheng13ca61a882017-08-25 15:11:252942 if 'interface_provider_specs' in json_content:
2943 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362944 else:
2945 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2946 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2947 if (manifest_pattern.search(f.LocalPath()) and not
2948 test_manifest_pattern.search(f.LocalPath())):
2949 # We expect all actual service manifest files to contain at least one
2950 # qualified reference to service_manager::Manifest.
2951 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2952 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172953 for pattern in file_patterns:
2954 if input_api.fnmatch.fnmatch(
2955 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042956 skip = False
2957 for exclude in exclude_paths:
2958 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2959 skip = True
2960 break
2961 if skip:
2962 continue
Daniel Cheng13ca61a882017-08-25 15:11:252963 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172964 break
2965
Daniel Cheng7052cdf2017-11-21 19:23:292966 return to_check
2967
2968
2969def _CheckIpcOwners(input_api, output_api):
2970 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2971 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2972
2973 if to_check:
2974 # If there are any OWNERS files to check, there are IPC-related changes in
2975 # this CL. Auto-CC the review list.
2976 output_api.AppendCC('[email protected]')
2977
2978 # Go through the OWNERS files to check, filtering out rules that are already
2979 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172980 for owners_file, patterns in to_check.iteritems():
2981 try:
2982 with file(owners_file) as f:
2983 lines = set(f.read().splitlines())
2984 for entry in patterns.itervalues():
2985 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2986 ]
2987 except IOError:
2988 # No OWNERS file, so all the rules are definitely missing.
2989 continue
2990
2991 # All the remaining lines weren't found in OWNERS files, so emit an error.
2992 errors = []
2993 for owners_file, patterns in to_check.iteritems():
2994 missing_lines = []
2995 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502996 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172997 missing_lines.extend(entry['rules'])
2998 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2999 if missing_lines:
3000 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053001 'Because of the presence of files:\n%s\n\n'
3002 '%s needs the following %d lines added:\n\n%s' %
3003 ('\n'.join(files), owners_file, len(missing_lines),
3004 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173005
3006 results = []
3007 if errors:
vabrf5ce3bf92016-07-11 14:52:413008 if input_api.is_committing:
3009 output = output_api.PresubmitError
3010 else:
3011 output = output_api.PresubmitPromptWarning
3012 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593013 'Found OWNERS files that need to be updated for IPC security ' +
3014 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173015 long_text='\n\n'.join(errors)))
3016
3017 return results
3018
3019
jbriance9e12f162016-11-25 07:57:503020def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313021 """Checks that added or removed lines in non third party affected
3022 header files do not lead to new useless class or struct forward
3023 declaration.
jbriance9e12f162016-11-25 07:57:503024 """
3025 results = []
3026 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3027 input_api.re.MULTILINE)
3028 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3029 input_api.re.MULTILINE)
3030 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313031 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193032 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493033 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313034 continue
3035
jbriance9e12f162016-11-25 07:57:503036 if not f.LocalPath().endswith('.h'):
3037 continue
3038
3039 contents = input_api.ReadFile(f)
3040 fwd_decls = input_api.re.findall(class_pattern, contents)
3041 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3042
3043 useless_fwd_decls = []
3044 for decl in fwd_decls:
3045 count = sum(1 for _ in input_api.re.finditer(
3046 r'\b%s\b' % input_api.re.escape(decl), contents))
3047 if count == 1:
3048 useless_fwd_decls.append(decl)
3049
3050 if not useless_fwd_decls:
3051 continue
3052
3053 for line in f.GenerateScmDiff().splitlines():
3054 if (line.startswith('-') and not line.startswith('--') or
3055 line.startswith('+') and not line.startswith('++')):
3056 for decl in useless_fwd_decls:
3057 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3058 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243059 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503060 (f.LocalPath(), decl)))
3061 useless_fwd_decls.remove(decl)
3062
3063 return results
3064
Jinsong Fan91ebbbd2019-04-16 14:57:173065def _CheckAndroidDebuggableBuild(input_api, output_api):
3066 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3067 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3068 this is a debuggable build of Android.
3069 """
3070 build_type_check_pattern = input_api.re.compile(
3071 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3072
3073 errors = []
3074
3075 sources = lambda affected_file: input_api.FilterSourceFile(
3076 affected_file,
3077 black_list=(_EXCLUDED_PATHS +
3078 _TEST_CODE_EXCLUDED_PATHS +
3079 input_api.DEFAULT_BLACK_LIST +
3080 (r"^android_webview[\\/]support_library[\\/]"
3081 "boundary_interfaces[\\/]",
3082 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3083 r'^third_party[\\/].*',
3084 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3085 r"webview[\\/]chromium[\\/]License.*",)),
3086 white_list=[r'.*\.java$'])
3087
3088 for f in input_api.AffectedSourceFiles(sources):
3089 for line_num, line in f.ChangedContents():
3090 if build_type_check_pattern.search(line):
3091 errors.append("%s:%d" % (f.LocalPath(), line_num))
3092
3093 results = []
3094
3095 if errors:
3096 results.append(output_api.PresubmitPromptWarning(
3097 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3098 ' Please use BuildInfo.isDebugAndroid() instead.',
3099 errors))
3100
3101 return results
jbriance9e12f162016-11-25 07:57:503102
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493103# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293104def _CheckAndroidToastUsage(input_api, output_api):
3105 """Checks that code uses org.chromium.ui.widget.Toast instead of
3106 android.widget.Toast (Chromium Toast doesn't force hardware
3107 acceleration on low-end devices, saving memory).
3108 """
3109 toast_import_pattern = input_api.re.compile(
3110 r'^import android\.widget\.Toast;$')
3111
3112 errors = []
3113
3114 sources = lambda affected_file: input_api.FilterSourceFile(
3115 affected_file,
3116 black_list=(_EXCLUDED_PATHS +
3117 _TEST_CODE_EXCLUDED_PATHS +
3118 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043119 (r'^chromecast[\\/].*',
3120 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493121 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293122
3123 for f in input_api.AffectedSourceFiles(sources):
3124 for line_num, line in f.ChangedContents():
3125 if toast_import_pattern.search(line):
3126 errors.append("%s:%d" % (f.LocalPath(), line_num))
3127
3128 results = []
3129
3130 if errors:
3131 results.append(output_api.PresubmitError(
3132 'android.widget.Toast usage is detected. Android toasts use hardware'
3133 ' acceleration, and can be\ncostly on low-end devices. Please use'
3134 ' org.chromium.ui.widget.Toast instead.\n'
3135 'Contact [email protected] if you have any questions.',
3136 errors))
3137
3138 return results
3139
3140
dgnaa68d5e2015-06-10 10:08:223141def _CheckAndroidCrLogUsage(input_api, output_api):
3142 """Checks that new logs using org.chromium.base.Log:
3143 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513144 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223145 """
pkotwicza1dd0b002016-05-16 14:41:043146
torne89540622017-03-24 19:41:303147 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043148 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303149 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043150 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303151 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043152 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3153 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093154 # The customtabs_benchmark is a small app that does not depend on Chromium
3155 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043156 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043157 ]
3158
dgnaa68d5e2015-06-10 10:08:223159 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123160 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3161 class_in_base_pattern = input_api.re.compile(
3162 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3163 has_some_log_import_pattern = input_api.re.compile(
3164 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223165 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123166 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223167 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463168 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223169
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463170 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493171 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043172 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123173
dgnaa68d5e2015-06-10 10:08:223174 tag_decl_errors = []
3175 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123176 tag_errors = []
dgn38736db2015-09-18 19:20:513177 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123178 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223179
3180 for f in input_api.AffectedSourceFiles(sources):
3181 file_content = input_api.ReadFile(f)
3182 has_modified_logs = False
3183
3184 # Per line checks
dgn87d9fb62015-06-12 09:15:123185 if (cr_log_import_pattern.search(file_content) or
3186 (class_in_base_pattern.search(file_content) and
3187 not has_some_log_import_pattern.search(file_content))):
3188 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223189 for line_num, line in f.ChangedContents():
3190
3191 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123192 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223193 if match:
3194 has_modified_logs = True
3195
3196 # Make sure it uses "TAG"
3197 if not match.group('tag') == 'TAG':
3198 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123199 else:
3200 # Report non cr Log function calls in changed lines
3201 for line_num, line in f.ChangedContents():
3202 if log_call_pattern.search(line):
3203 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223204
3205 # Per file checks
3206 if has_modified_logs:
3207 # Make sure the tag is using the "cr" prefix and is not too long
3208 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513209 tag_name = match.group('name') if match else None
3210 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223211 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513212 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223213 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513214 elif '.' in tag_name:
3215 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223216
3217 results = []
3218 if tag_decl_errors:
3219 results.append(output_api.PresubmitPromptWarning(
3220 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513221 '"private static final String TAG = "<package tag>".\n'
3222 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223223 tag_decl_errors))
3224
3225 if tag_length_errors:
3226 results.append(output_api.PresubmitError(
3227 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513228 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223229 tag_length_errors))
3230
3231 if tag_errors:
3232 results.append(output_api.PresubmitPromptWarning(
3233 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3234 tag_errors))
3235
dgn87d9fb62015-06-12 09:15:123236 if util_log_errors:
dgn4401aa52015-04-29 16:26:173237 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123238 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3239 util_log_errors))
3240
dgn38736db2015-09-18 19:20:513241 if tag_with_dot_errors:
3242 results.append(output_api.PresubmitPromptWarning(
3243 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3244 tag_with_dot_errors))
3245
dgn4401aa52015-04-29 16:26:173246 return results
3247
3248
Yoland Yanb92fa522017-08-28 17:37:063249def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3250 """Checks that junit.framework.* is no longer used."""
3251 deprecated_junit_framework_pattern = input_api.re.compile(
3252 r'^import junit\.framework\..*;',
3253 input_api.re.MULTILINE)
3254 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493255 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063256 errors = []
3257 for f in input_api.AffectedFiles(sources):
3258 for line_num, line in f.ChangedContents():
3259 if deprecated_junit_framework_pattern.search(line):
3260 errors.append("%s:%d" % (f.LocalPath(), line_num))
3261
3262 results = []
3263 if errors:
3264 results.append(output_api.PresubmitError(
3265 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3266 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3267 ' if you have any question.', errors))
3268 return results
3269
3270
3271def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3272 """Checks that if new Java test classes have inheritance.
3273 Either the new test class is JUnit3 test or it is a JUnit4 test class
3274 with a base class, either case is undesirable.
3275 """
3276 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3277
3278 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493279 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063280 errors = []
3281 for f in input_api.AffectedFiles(sources):
3282 if not f.OldContents():
3283 class_declaration_start_flag = False
3284 for line_num, line in f.ChangedContents():
3285 if class_declaration_pattern.search(line):
3286 class_declaration_start_flag = True
3287 if class_declaration_start_flag and ' extends ' in line:
3288 errors.append('%s:%d' % (f.LocalPath(), line_num))
3289 if '{' in line:
3290 class_declaration_start_flag = False
3291
3292 results = []
3293 if errors:
3294 results.append(output_api.PresubmitPromptWarning(
3295 'The newly created files include Test classes that inherits from base'
3296 ' class. Please do not use inheritance in JUnit4 tests or add new'
3297 ' JUnit3 tests. Contact [email protected] if you have any'
3298 ' questions.', errors))
3299 return results
3300
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203301
yolandyan45001472016-12-21 21:12:423302def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3303 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3304 deprecated_annotation_import_pattern = input_api.re.compile(
3305 r'^import android\.test\.suitebuilder\.annotation\..*;',
3306 input_api.re.MULTILINE)
3307 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493308 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423309 errors = []
3310 for f in input_api.AffectedFiles(sources):
3311 for line_num, line in f.ChangedContents():
3312 if deprecated_annotation_import_pattern.search(line):
3313 errors.append("%s:%d" % (f.LocalPath(), line_num))
3314
3315 results = []
3316 if errors:
3317 results.append(output_api.PresubmitError(
3318 'Annotations in android.test.suitebuilder.annotation have been'
3319 ' deprecated since API level 24. Please use android.support.test.filters'
3320 ' from //third_party/android_support_test_runner:runner_java instead.'
3321 ' Contact [email protected] if you have any questions.', errors))
3322 return results
3323
3324
agrieve7b6479d82015-10-07 14:24:223325def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3326 """Checks if MDPI assets are placed in a correct directory."""
3327 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3328 ('/res/drawable/' in f.LocalPath() or
3329 '/res/drawable-ldrtl/' in f.LocalPath()))
3330 errors = []
3331 for f in input_api.AffectedFiles(include_deletes=False,
3332 file_filter=file_filter):
3333 errors.append(' %s' % f.LocalPath())
3334
3335 results = []
3336 if errors:
3337 results.append(output_api.PresubmitError(
3338 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3339 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3340 '/res/drawable-ldrtl/.\n'
3341 'Contact [email protected] if you have questions.', errors))
3342 return results
3343
3344
Nate Fischer535972b2017-09-16 01:06:183345def _CheckAndroidWebkitImports(input_api, output_api):
3346 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353347 android.webview.ValueCallback except in the WebView glue layer
3348 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183349 """
3350 valuecallback_import_pattern = input_api.re.compile(
3351 r'^import android\.webkit\.ValueCallback;$')
3352
3353 errors = []
3354
3355 sources = lambda affected_file: input_api.FilterSourceFile(
3356 affected_file,
3357 black_list=(_EXCLUDED_PATHS +
3358 _TEST_CODE_EXCLUDED_PATHS +
3359 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353360 (r'^android_webview[\\/]glue[\\/].*',
3361 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493362 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183363
3364 for f in input_api.AffectedSourceFiles(sources):
3365 for line_num, line in f.ChangedContents():
3366 if valuecallback_import_pattern.search(line):
3367 errors.append("%s:%d" % (f.LocalPath(), line_num))
3368
3369 results = []
3370
3371 if errors:
3372 results.append(output_api.PresubmitError(
3373 'android.webkit.ValueCallback usage is detected outside of the glue'
3374 ' layer. To stay compatible with the support library, android.webkit.*'
3375 ' classes should only be used inside the glue layer and'
3376 ' org.chromium.base.Callback should be used instead.',
3377 errors))
3378
3379 return results
3380
3381
Becky Zhou7c69b50992018-12-10 19:37:573382def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3383 """Checks Android XML styles """
3384 import sys
3385 original_sys_path = sys.path
3386 try:
3387 sys.path = sys.path + [input_api.os_path.join(
3388 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3389 import checkxmlstyle
3390 finally:
3391 # Restore sys.path to what it was before.
3392 sys.path = original_sys_path
3393
3394 if is_check_on_upload:
3395 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3396 else:
3397 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3398
3399
agrievef32bcc72016-04-04 14:57:403400class PydepsChecker(object):
3401 def __init__(self, input_api, pydeps_files):
3402 self._file_cache = {}
3403 self._input_api = input_api
3404 self._pydeps_files = pydeps_files
3405
3406 def _LoadFile(self, path):
3407 """Returns the list of paths within a .pydeps file relative to //."""
3408 if path not in self._file_cache:
3409 with open(path) as f:
3410 self._file_cache[path] = f.read()
3411 return self._file_cache[path]
3412
3413 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3414 """Returns an interable of paths within the .pydep, relativized to //."""
3415 os_path = self._input_api.os_path
3416 pydeps_dir = os_path.dirname(pydeps_path)
3417 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3418 if not l.startswith('*'))
3419 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3420
3421 def _CreateFilesToPydepsMap(self):
3422 """Returns a map of local_path -> list_of_pydeps."""
3423 ret = {}
3424 for pydep_local_path in self._pydeps_files:
3425 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3426 ret.setdefault(path, []).append(pydep_local_path)
3427 return ret
3428
3429 def ComputeAffectedPydeps(self):
3430 """Returns an iterable of .pydeps files that might need regenerating."""
3431 affected_pydeps = set()
3432 file_to_pydeps_map = None
3433 for f in self._input_api.AffectedFiles(include_deletes=True):
3434 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463435 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3436 # subrepositories. We can't figure out which files change, so re-check
3437 # all files.
3438 # Changes to print_python_deps.py affect all .pydeps.
3439 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403440 return self._pydeps_files
3441 elif local_path.endswith('.pydeps'):
3442 if local_path in self._pydeps_files:
3443 affected_pydeps.add(local_path)
3444 elif local_path.endswith('.py'):
3445 if file_to_pydeps_map is None:
3446 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3447 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3448 return affected_pydeps
3449
3450 def DetermineIfStale(self, pydeps_path):
3451 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413452 import difflib
John Budorick47ca3fe2018-02-10 00:53:103453 import os
3454
agrievef32bcc72016-04-04 14:57:403455 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3456 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103457 env = dict(os.environ)
3458 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403459 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103460 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413461 old_contents = old_pydeps_data[2:]
3462 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403463 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413464 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403465
3466
Tibor Goldschwendt360793f72019-06-25 18:23:493467def _ParseGclientArgs():
3468 args = {}
3469 with open('build/config/gclient_args.gni', 'r') as f:
3470 for line in f:
3471 line = line.strip()
3472 if not line or line.startswith('#'):
3473 continue
3474 attribute, value = line.split('=')
3475 args[attribute.strip()] = value.strip()
3476 return args
3477
3478
agrievef32bcc72016-04-04 14:57:403479def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3480 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403481 # This check is for Python dependency lists (.pydeps files), and involves
3482 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3483 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283484 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003485 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493486 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403487 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3488 results = []
3489 # First, check for new / deleted .pydeps.
3490 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033491 # Check whether we are running the presubmit check for a file in src.
3492 # f.LocalPath is relative to repo (src, or internal repo).
3493 # os_path.exists is relative to src repo.
3494 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3495 # to src and we can conclude that the pydeps is in src.
3496 if input_api.os_path.exists(f.LocalPath()):
3497 if f.LocalPath().endswith('.pydeps'):
3498 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3499 results.append(output_api.PresubmitError(
3500 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3501 'remove %s' % f.LocalPath()))
3502 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3503 results.append(output_api.PresubmitError(
3504 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3505 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403506
3507 if results:
3508 return results
3509
3510 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3511
3512 for pydep_path in checker.ComputeAffectedPydeps():
3513 try:
phajdan.jr0d9878552016-11-04 10:49:413514 result = checker.DetermineIfStale(pydep_path)
3515 if result:
3516 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403517 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413518 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3519 'To regenerate, run:\n\n %s' %
3520 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403521 except input_api.subprocess.CalledProcessError as error:
3522 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3523 long_text=error.output)]
3524
3525 return results
3526
3527
glidere61efad2015-02-18 17:39:433528def _CheckSingletonInHeaders(input_api, output_api):
3529 """Checks to make sure no header files have |Singleton<|."""
3530 def FileFilter(affected_file):
3531 # It's ok for base/memory/singleton.h to have |Singleton<|.
3532 black_list = (_EXCLUDED_PATHS +
3533 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043534 (r"^base[\\/]memory[\\/]singleton\.h$",
3535 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473536 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433537 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3538
sergeyu34d21222015-09-16 00:11:443539 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433540 files = []
3541 for f in input_api.AffectedSourceFiles(FileFilter):
3542 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3543 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3544 contents = input_api.ReadFile(f)
3545 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243546 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433547 pattern.search(line)):
3548 files.append(f)
3549 break
3550
3551 if files:
yolandyandaabc6d2016-04-18 18:29:393552 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443553 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433554 'Please move them to an appropriate source file so that the ' +
3555 'template gets instantiated in a single compilation unit.',
3556 files) ]
3557 return []
3558
3559
[email protected]fd20b902014-05-09 02:14:533560_DEPRECATED_CSS = [
3561 # Values
3562 ( "-webkit-box", "flex" ),
3563 ( "-webkit-inline-box", "inline-flex" ),
3564 ( "-webkit-flex", "flex" ),
3565 ( "-webkit-inline-flex", "inline-flex" ),
3566 ( "-webkit-min-content", "min-content" ),
3567 ( "-webkit-max-content", "max-content" ),
3568
3569 # Properties
3570 ( "-webkit-background-clip", "background-clip" ),
3571 ( "-webkit-background-origin", "background-origin" ),
3572 ( "-webkit-background-size", "background-size" ),
3573 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443574 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533575
3576 # Functions
3577 ( "-webkit-gradient", "gradient" ),
3578 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3579 ( "-webkit-linear-gradient", "linear-gradient" ),
3580 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3581 ( "-webkit-radial-gradient", "radial-gradient" ),
3582 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3583]
3584
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203585
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493586# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243587def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533588 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253589 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343590 documentation and iOS CSS for dom distiller
3591 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253592 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533593 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493594 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253595 black_list = (_EXCLUDED_PATHS +
3596 _TEST_CODE_EXCLUDED_PATHS +
3597 input_api.DEFAULT_BLACK_LIST +
3598 (r"^chrome/common/extensions/docs",
3599 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343600 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443601 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253602 r"^native_client_sdk"))
3603 file_filter = lambda f: input_api.FilterSourceFile(
3604 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533605 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3606 for line_num, line in fpath.ChangedContents():
3607 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023608 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533609 results.append(output_api.PresubmitError(
3610 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3611 (fpath.LocalPath(), line_num, deprecated_value, value)))
3612 return results
3613
mohan.reddyf21db962014-10-16 12:26:473614
rlanday6802cf632017-05-30 17:48:363615def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363616 bad_files = {}
3617 for f in input_api.AffectedFiles(include_deletes=False):
3618 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493619 not f.LocalPath().startswith('third_party/blink') and
3620 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363621 continue
3622
Daniel Bratell65b033262019-04-23 08:17:063623 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363624 continue
3625
Vaclav Brozekd5de76a2018-03-17 07:57:503626 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363627 if "#include" in line and "../" in line]
3628 if not relative_includes:
3629 continue
3630 bad_files[f.LocalPath()] = relative_includes
3631
3632 if not bad_files:
3633 return []
3634
3635 error_descriptions = []
3636 for file_path, bad_lines in bad_files.iteritems():
3637 error_description = file_path
3638 for line in bad_lines:
3639 error_description += '\n ' + line
3640 error_descriptions.append(error_description)
3641
3642 results = []
3643 results.append(output_api.PresubmitError(
3644 'You added one or more relative #include paths (including "../").\n'
3645 'These shouldn\'t be used because they can be used to include headers\n'
3646 'from code that\'s not correctly specified as a dependency in the\n'
3647 'relevant BUILD.gn file(s).',
3648 error_descriptions))
3649
3650 return results
3651
Takeshi Yoshinoe387aa32017-08-02 13:16:133652
Daniel Bratell65b033262019-04-23 08:17:063653def _CheckForCcIncludes(input_api, output_api):
3654 """Check that nobody tries to include a cc file. It's a relatively
3655 common error which results in duplicate symbols in object
3656 files. This may not always break the build until someone later gets
3657 very confusing linking errors."""
3658 results = []
3659 for f in input_api.AffectedFiles(include_deletes=False):
3660 # We let third_party code do whatever it wants
3661 if (f.LocalPath().startswith('third_party') and
3662 not f.LocalPath().startswith('third_party/blink') and
3663 not f.LocalPath().startswith('third_party\\blink')):
3664 continue
3665
3666 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3667 continue
3668
3669 for _, line in f.ChangedContents():
3670 if line.startswith('#include "'):
3671 included_file = line.split('"')[1]
3672 if _IsCPlusPlusFile(input_api, included_file):
3673 # The most common naming for external files with C++ code,
3674 # apart from standard headers, is to call them foo.inc, but
3675 # Chromium sometimes uses foo-inc.cc so allow that as well.
3676 if not included_file.endswith(('.h', '-inc.cc')):
3677 results.append(output_api.PresubmitError(
3678 'Only header files or .inc files should be included in other\n'
3679 'C++ files. Compiling the contents of a cc file more than once\n'
3680 'will cause duplicate information in the build which may later\n'
3681 'result in strange link_errors.\n' +
3682 f.LocalPath() + ':\n ' +
3683 line))
3684
3685 return results
3686
3687
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203688def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3689 if not isinstance(key, ast.Str):
3690 return 'Key at line %d must be a string literal' % key.lineno
3691 if not isinstance(value, ast.Dict):
3692 return 'Value at line %d must be a dict' % value.lineno
3693 if len(value.keys) != 1:
3694 return 'Dict at line %d must have single entry' % value.lineno
3695 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3696 return (
3697 'Entry at line %d must have a string literal \'filepath\' as key' %
3698 value.lineno)
3699 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133700
Takeshi Yoshinoe387aa32017-08-02 13:16:133701
Sergey Ulanov4af16052018-11-08 02:41:463702def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203703 if not isinstance(key, ast.Str):
3704 return 'Key at line %d must be a string literal' % key.lineno
3705 if not isinstance(value, ast.List):
3706 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463707 for element in value.elts:
3708 if not isinstance(element, ast.Str):
3709 return 'Watchlist elements on line %d is not a string' % key.lineno
3710 if not email_regex.match(element.s):
3711 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3712 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203713 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133714
Takeshi Yoshinoe387aa32017-08-02 13:16:133715
Sergey Ulanov4af16052018-11-08 02:41:463716def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203717 mismatch_template = (
3718 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3719 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133720
Sergey Ulanov4af16052018-11-08 02:41:463721 email_regex = input_api.re.compile(
3722 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3723
3724 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203725 i = 0
3726 last_key = ''
3727 while True:
3728 if i >= len(wd_dict.keys):
3729 if i >= len(w_dict.keys):
3730 return None
3731 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3732 elif i >= len(w_dict.keys):
3733 return (
3734 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133735
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203736 wd_key = wd_dict.keys[i]
3737 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133738
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203739 result = _CheckWatchlistDefinitionsEntrySyntax(
3740 wd_key, wd_dict.values[i], ast)
3741 if result is not None:
3742 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133743
Sergey Ulanov4af16052018-11-08 02:41:463744 result = _CheckWatchlistsEntrySyntax(
3745 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203746 if result is not None:
3747 return 'Bad entry in WATCHLISTS dict: %s' % result
3748
3749 if wd_key.s != w_key.s:
3750 return mismatch_template % (
3751 '%s at line %d' % (wd_key.s, wd_key.lineno),
3752 '%s at line %d' % (w_key.s, w_key.lineno))
3753
3754 if wd_key.s < last_key:
3755 return (
3756 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3757 (wd_key.lineno, w_key.lineno))
3758 last_key = wd_key.s
3759
3760 i = i + 1
3761
3762
Sergey Ulanov4af16052018-11-08 02:41:463763def _CheckWATCHLISTSSyntax(expression, input_api):
3764 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203765 if not isinstance(expression, ast.Expression):
3766 return 'WATCHLISTS file must contain a valid expression'
3767 dictionary = expression.body
3768 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3769 return 'WATCHLISTS file must have single dict with exactly two entries'
3770
3771 first_key = dictionary.keys[0]
3772 first_value = dictionary.values[0]
3773 second_key = dictionary.keys[1]
3774 second_value = dictionary.values[1]
3775
3776 if (not isinstance(first_key, ast.Str) or
3777 first_key.s != 'WATCHLIST_DEFINITIONS' or
3778 not isinstance(first_value, ast.Dict)):
3779 return (
3780 'The first entry of the dict in WATCHLISTS file must be '
3781 'WATCHLIST_DEFINITIONS dict')
3782
3783 if (not isinstance(second_key, ast.Str) or
3784 second_key.s != 'WATCHLISTS' or
3785 not isinstance(second_value, ast.Dict)):
3786 return (
3787 'The second entry of the dict in WATCHLISTS file must be '
3788 'WATCHLISTS dict')
3789
Sergey Ulanov4af16052018-11-08 02:41:463790 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133791
3792
3793def _CheckWATCHLISTS(input_api, output_api):
3794 for f in input_api.AffectedFiles(include_deletes=False):
3795 if f.LocalPath() == 'WATCHLISTS':
3796 contents = input_api.ReadFile(f, 'r')
3797
3798 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203799 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133800 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203801 # Get an AST tree for it and scan the tree for detailed style checking.
3802 expression = input_api.ast.parse(
3803 contents, filename='WATCHLISTS', mode='eval')
3804 except ValueError as e:
3805 return [output_api.PresubmitError(
3806 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3807 except SyntaxError as e:
3808 return [output_api.PresubmitError(
3809 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3810 except TypeError as e:
3811 return [output_api.PresubmitError(
3812 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133813
Sergey Ulanov4af16052018-11-08 02:41:463814 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203815 if result is not None:
3816 return [output_api.PresubmitError(result)]
3817 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133818
3819 return []
3820
3821
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193822def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3823 """Checks that newly added header files have corresponding GN changes.
3824 Note that this is only a heuristic. To be precise, run script:
3825 build/check_gn_headers.py.
3826 """
3827
3828 def headers(f):
3829 return input_api.FilterSourceFile(
3830 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3831
3832 new_headers = []
3833 for f in input_api.AffectedSourceFiles(headers):
3834 if f.Action() != 'A':
3835 continue
3836 new_headers.append(f.LocalPath())
3837
3838 def gn_files(f):
3839 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3840
3841 all_gn_changed_contents = ''
3842 for f in input_api.AffectedSourceFiles(gn_files):
3843 for _, line in f.ChangedContents():
3844 all_gn_changed_contents += line
3845
3846 problems = []
3847 for header in new_headers:
3848 basename = input_api.os_path.basename(header)
3849 if basename not in all_gn_changed_contents:
3850 problems.append(header)
3851
3852 if problems:
3853 return [output_api.PresubmitPromptWarning(
3854 'Missing GN changes for new header files', items=sorted(problems),
3855 long_text='Please double check whether newly added header files need '
3856 'corresponding changes in gn or gni files.\nThis checking is only a '
3857 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3858 'Read https://crbug.com/661774 for more info.')]
3859 return []
3860
3861
Michael Giuffridad3bc8672018-10-25 22:48:023862def _CheckCorrectProductNameInMessages(input_api, output_api):
3863 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3864
3865 This assumes we won't intentionally reference one product from the other
3866 product.
3867 """
3868 all_problems = []
3869 test_cases = [{
3870 "filename_postfix": "google_chrome_strings.grd",
3871 "correct_name": "Chrome",
3872 "incorrect_name": "Chromium",
3873 }, {
3874 "filename_postfix": "chromium_strings.grd",
3875 "correct_name": "Chromium",
3876 "incorrect_name": "Chrome",
3877 }]
3878
3879 for test_case in test_cases:
3880 problems = []
3881 filename_filter = lambda x: x.LocalPath().endswith(
3882 test_case["filename_postfix"])
3883
3884 # Check each new line. Can yield false positives in multiline comments, but
3885 # easier than trying to parse the XML because messages can have nested
3886 # children, and associating message elements with affected lines is hard.
3887 for f in input_api.AffectedSourceFiles(filename_filter):
3888 for line_num, line in f.ChangedContents():
3889 if "<message" in line or "<!--" in line or "-->" in line:
3890 continue
3891 if test_case["incorrect_name"] in line:
3892 problems.append(
3893 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3894
3895 if problems:
3896 message = (
3897 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3898 % (test_case["correct_name"], test_case["correct_name"],
3899 test_case["incorrect_name"]))
3900 all_problems.append(
3901 output_api.PresubmitPromptWarning(message, items=problems))
3902
3903 return all_problems
3904
3905
Dirk Pranke3c18a382019-03-15 01:07:513906def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3907 # TODO(crbug.com/941824): We need to make sure the entries in
3908 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3909 # so that users of //buildtools in other projects get the same tooling
3910 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3911 # support to gclient, we can eliminate the duplication and delete
3912 # this presubmit check.
3913
3914 # Update this regexp if new revisions are added to the files.
3915 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013916 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513917
3918 # If a user is changing one revision, they need to change the same
3919 # line in both files. This means that any given change should contain
3920 # exactly the same list of changed lines that match the regexps. The
3921 # replace(' ', '') call allows us to ignore whitespace changes to the
3922 # lines. The 'long_text' parameter to the error will contain the
3923 # list of changed lines in both files, which should make it easy enough
3924 # to spot the error without going overboard in this implementation.
3925 revs_changes = {
3926 'DEPS': {},
3927 'buildtools/DEPS': {},
3928 }
3929 long_text = ''
3930
3931 for f in input_api.AffectedFiles(
3932 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3933 for line_num, line in f.ChangedContents():
3934 if rev_regexp.search(line):
3935 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3936 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3937
3938 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3939 return [output_api.PresubmitError(
3940 'Change buildtools revisions in sync in both //DEPS and '
3941 '//buildtools/DEPS.', long_text=long_text + '\n')]
3942 else:
3943 return []
3944
3945
Daniel Bratell93eb6c62019-04-29 20:13:363946def _CheckForTooLargeFiles(input_api, output_api):
3947 """Avoid large files, especially binary files, in the repository since
3948 git doesn't scale well for those. They will be in everyone's repo
3949 clones forever, forever making Chromium slower to clone and work
3950 with."""
3951
3952 # Uploading files to cloud storage is not trivial so we don't want
3953 # to set the limit too low, but the upper limit for "normal" large
3954 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
3955 # anything over 20 MB is exceptional.
3956 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
3957
3958 too_large_files = []
3959 for f in input_api.AffectedFiles():
3960 # Check both added and modified files (but not deleted files).
3961 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:383962 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:363963 if size > TOO_LARGE_FILE_SIZE_LIMIT:
3964 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
3965
3966 if too_large_files:
3967 message = (
3968 'Do not commit large files to git since git scales badly for those.\n' +
3969 'Instead put the large files in cloud storage and use DEPS to\n' +
3970 'fetch them.\n' + '\n'.join(too_large_files)
3971 )
3972 return [output_api.PresubmitError(
3973 'Too large files found in commit', long_text=message + '\n')]
3974 else:
3975 return []
3976
Max Morozb47503b2019-08-08 21:03:273977
3978def _CheckFuzzTargets(input_api, output_api):
3979 """Checks specific for fuzz target sources."""
3980 EXPORTED_SYMBOLS = [
3981 'LLVMFuzzerInitialize',
3982 'LLVMFuzzerCustomMutator',
3983 'LLVMFuzzerCustomCrossOver',
3984 'LLVMFuzzerMutate',
3985 ]
3986
3987 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
3988
3989 def FilterFile(affected_file):
3990 """Ignore libFuzzer source code."""
3991 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
3992 black_list = r"^third_party[\\/]libFuzzer"
3993
3994 return input_api.FilterSourceFile(
3995 affected_file,
3996 white_list=[white_list],
3997 black_list=[black_list])
3998
3999 files_with_missing_header = []
4000 for f in input_api.AffectedSourceFiles(FilterFile):
4001 contents = input_api.ReadFile(f, 'r')
4002 if REQUIRED_HEADER in contents:
4003 continue
4004
4005 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4006 files_with_missing_header.append(f.LocalPath())
4007
4008 if not files_with_missing_header:
4009 return []
4010
4011 long_text = (
4012 'If you define any of the libFuzzer optional functions (%s), it is '
4013 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4014 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4015 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4016 'to access command line arguments passed to the fuzzer. Instead, prefer '
4017 'static initialization and shared resources as documented in '
4018 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4019 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4020 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4021 )
4022
4023 return [output_api.PresubmitPromptWarning(
4024 message="Missing '%s' in:" % REQUIRED_HEADER,
4025 items=files_with_missing_header,
4026 long_text=long_text)]
4027
4028
dgnaa68d5e2015-06-10 10:08:224029def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574030 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224031 results = []
dgnaa68d5e2015-06-10 10:08:224032 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174033 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224034 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294035 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064036 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4037 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424038 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184039 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574040 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
4041 return results
4042
4043def _AndroidSpecificOnCommitChecks(input_api, output_api):
4044 """Groups commit checks that target android code."""
4045 results = []
4046 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224047 return results
4048
4049
[email protected]22c9bd72011-03-27 16:47:394050def _CommonChecks(input_api, output_api):
4051 """Checks common to both upload and commit."""
4052 results = []
4053 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384054 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544055 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084056
4057 author = input_api.change.author_email
4058 if author and author not in _KNOWN_ROBOTS:
4059 results.extend(
4060 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4061
[email protected]55459852011-08-10 15:17:194062 results.extend(
[email protected]760deea2013-12-10 19:33:494063 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234064 results.extend(
4065 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544066 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184067 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344068 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524069 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224070 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444071 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594072 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314073 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064074 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124075 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184076 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224077 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304078 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494079 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034080 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494081 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444082 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274083 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074084 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544085 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444086 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394087 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554088 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044089 results.extend(
4090 input_api.canned_checks.CheckChangeHasNoTabs(
4091 input_api,
4092 output_api,
4093 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404094 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164095 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084096 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244097 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474098 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044099 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054100 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144101 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234102 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434103 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404104 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154105 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174106 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504107 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364108 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064109 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134110 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434111 results.extend(input_api.RunTests(
4112 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144113 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024114 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514115 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364116 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004117 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244118
Vaclav Brozekcdc7defb2018-03-20 09:54:354119 for f in input_api.AffectedFiles():
4120 path, name = input_api.os_path.split(f.LocalPath())
4121 if name == 'PRESUBMIT.py':
4122 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004123 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4124 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074125 # The PRESUBMIT.py file (and the directory containing it) might
4126 # have been affected by being moved or removed, so only try to
4127 # run the tests if they still exist.
4128 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4129 input_api, output_api, full_path,
4130 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394131 return results
[email protected]1f7b4172010-01-28 01:17:344132
[email protected]b337cb5b2011-01-23 21:24:054133
[email protected]b8079ae4a2012-12-05 19:56:494134def _CheckPatchFiles(input_api, output_api):
4135 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4136 if f.LocalPath().endswith(('.orig', '.rej'))]
4137 if problems:
4138 return [output_api.PresubmitError(
4139 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034140 else:
4141 return []
[email protected]b8079ae4a2012-12-05 19:56:494142
4143
Kent Tamura5a8755d2017-06-29 23:37:074144def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214145 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4146 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4147 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074148 include_re = input_api.re.compile(
4149 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4150 extension_re = input_api.re.compile(r'\.[a-z]+$')
4151 errors = []
4152 for f in input_api.AffectedFiles():
4153 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4154 continue
4155 found_line_number = None
4156 found_macro = None
4157 for line_num, line in f.ChangedContents():
4158 match = macro_re.search(line)
4159 if match:
4160 found_line_number = line_num
4161 found_macro = match.group(2)
4162 break
4163 if not found_line_number:
4164 continue
4165
4166 found_include = False
4167 for line in f.NewContents():
4168 if include_re.search(line):
4169 found_include = True
4170 break
4171 if found_include:
4172 continue
4173
4174 if not f.LocalPath().endswith('.h'):
4175 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4176 try:
4177 content = input_api.ReadFile(primary_header_path, 'r')
4178 if include_re.search(content):
4179 continue
4180 except IOError:
4181 pass
4182 errors.append('%s:%d %s macro is used without including build/'
4183 'build_config.h.'
4184 % (f.LocalPath(), found_line_number, found_macro))
4185 if errors:
4186 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4187 return []
4188
4189
[email protected]b00342e7f2013-03-26 16:21:544190def _DidYouMeanOSMacro(bad_macro):
4191 try:
4192 return {'A': 'OS_ANDROID',
4193 'B': 'OS_BSD',
4194 'C': 'OS_CHROMEOS',
4195 'F': 'OS_FREEBSD',
4196 'L': 'OS_LINUX',
4197 'M': 'OS_MACOSX',
4198 'N': 'OS_NACL',
4199 'O': 'OS_OPENBSD',
4200 'P': 'OS_POSIX',
4201 'S': 'OS_SOLARIS',
4202 'W': 'OS_WIN'}[bad_macro[3].upper()]
4203 except KeyError:
4204 return ''
4205
4206
4207def _CheckForInvalidOSMacrosInFile(input_api, f):
4208 """Check for sensible looking, totally invalid OS macros."""
4209 preprocessor_statement = input_api.re.compile(r'^\s*#')
4210 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4211 results = []
4212 for lnum, line in f.ChangedContents():
4213 if preprocessor_statement.search(line):
4214 for match in os_macro.finditer(line):
4215 if not match.group(1) in _VALID_OS_MACROS:
4216 good = _DidYouMeanOSMacro(match.group(1))
4217 did_you_mean = ' (did you mean %s?)' % good if good else ''
4218 results.append(' %s:%d %s%s' % (f.LocalPath(),
4219 lnum,
4220 match.group(1),
4221 did_you_mean))
4222 return results
4223
4224
4225def _CheckForInvalidOSMacros(input_api, output_api):
4226 """Check all affected files for invalid OS macros."""
4227 bad_macros = []
tzik3f295992018-12-04 20:32:234228 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474229 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544230 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4231
4232 if not bad_macros:
4233 return []
4234
4235 return [output_api.PresubmitError(
4236 'Possibly invalid OS macro[s] found. Please fix your code\n'
4237 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4238
lliabraa35bab3932014-10-01 12:16:444239
4240def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4241 """Check all affected files for invalid "if defined" macros."""
4242 ALWAYS_DEFINED_MACROS = (
4243 "TARGET_CPU_PPC",
4244 "TARGET_CPU_PPC64",
4245 "TARGET_CPU_68K",
4246 "TARGET_CPU_X86",
4247 "TARGET_CPU_ARM",
4248 "TARGET_CPU_MIPS",
4249 "TARGET_CPU_SPARC",
4250 "TARGET_CPU_ALPHA",
4251 "TARGET_IPHONE_SIMULATOR",
4252 "TARGET_OS_EMBEDDED",
4253 "TARGET_OS_IPHONE",
4254 "TARGET_OS_MAC",
4255 "TARGET_OS_UNIX",
4256 "TARGET_OS_WIN32",
4257 )
4258 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4259 results = []
4260 for lnum, line in f.ChangedContents():
4261 for match in ifdef_macro.finditer(line):
4262 if match.group(1) in ALWAYS_DEFINED_MACROS:
4263 always_defined = ' %s is always defined. ' % match.group(1)
4264 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4265 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4266 lnum,
4267 always_defined,
4268 did_you_mean))
4269 return results
4270
4271
4272def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4273 """Check all affected files for invalid "if defined" macros."""
4274 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054275 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444276 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054277 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214278 continue
lliabraa35bab3932014-10-01 12:16:444279 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4280 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4281
4282 if not bad_macros:
4283 return []
4284
4285 return [output_api.PresubmitError(
4286 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4287 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4288 bad_macros)]
4289
4290
mlamouria82272622014-09-16 18:45:044291def _CheckForIPCRules(input_api, output_api):
4292 """Check for same IPC rules described in
4293 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4294 """
4295 base_pattern = r'IPC_ENUM_TRAITS\('
4296 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4297 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4298
4299 problems = []
4300 for f in input_api.AffectedSourceFiles(None):
4301 local_path = f.LocalPath()
4302 if not local_path.endswith('.h'):
4303 continue
4304 for line_number, line in f.ChangedContents():
4305 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4306 problems.append(
4307 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4308
4309 if problems:
4310 return [output_api.PresubmitPromptWarning(
4311 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4312 else:
4313 return []
4314
[email protected]b00342e7f2013-03-26 16:21:544315
Stephen Martinis97a394142018-06-07 23:06:054316def _CheckForLongPathnames(input_api, output_api):
4317 """Check to make sure no files being submitted have long paths.
4318 This causes issues on Windows.
4319 """
4320 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194321 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054322 local_path = f.LocalPath()
4323 # Windows has a path limit of 260 characters. Limit path length to 200 so
4324 # that we have some extra for the prefix on dev machines and the bots.
4325 if len(local_path) > 200:
4326 problems.append(local_path)
4327
4328 if problems:
4329 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4330 else:
4331 return []
4332
4333
Daniel Bratell8ba52722018-03-02 16:06:144334def _CheckForIncludeGuards(input_api, output_api):
4335 """Check that header files have proper guards against multiple inclusion.
4336 If a file should not have such guards (and it probably should) then it
4337 should include the string "no-include-guard-because-multiply-included".
4338 """
Daniel Bratell6a75baef62018-06-04 10:04:454339 def is_chromium_header_file(f):
4340 # We only check header files under the control of the Chromium
4341 # project. That is, those outside third_party apart from
4342 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324343 # We also exclude *_message_generator.h headers as they use
4344 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454345 file_with_path = input_api.os_path.normpath(f.LocalPath())
4346 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324347 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454348 (not file_with_path.startswith('third_party') or
4349 file_with_path.startswith(
4350 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144351
4352 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344353 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144354
4355 errors = []
4356
Daniel Bratell6a75baef62018-06-04 10:04:454357 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144358 guard_name = None
4359 guard_line_number = None
4360 seen_guard_end = False
4361
4362 file_with_path = input_api.os_path.normpath(f.LocalPath())
4363 base_file_name = input_api.os_path.splitext(
4364 input_api.os_path.basename(file_with_path))[0]
4365 upper_base_file_name = base_file_name.upper()
4366
4367 expected_guard = replace_special_with_underscore(
4368 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144369
4370 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574371 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4372 # are too many (1000+) files with slight deviations from the
4373 # coding style. The most important part is that the include guard
4374 # is there, and that it's unique, not the name so this check is
4375 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144376 #
4377 # As code becomes more uniform, this could be made stricter.
4378
4379 guard_name_pattern_list = [
4380 # Anything with the right suffix (maybe with an extra _).
4381 r'\w+_H__?',
4382
Daniel Bratell39b5b062018-05-16 18:09:574383 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144384 r'\w+_h',
4385
4386 # Anything including the uppercase name of the file.
4387 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4388 upper_base_file_name)) + r'\w*',
4389 ]
4390 guard_name_pattern = '|'.join(guard_name_pattern_list)
4391 guard_pattern = input_api.re.compile(
4392 r'#ifndef\s+(' + guard_name_pattern + ')')
4393
4394 for line_number, line in enumerate(f.NewContents()):
4395 if 'no-include-guard-because-multiply-included' in line:
4396 guard_name = 'DUMMY' # To not trigger check outside the loop.
4397 break
4398
4399 if guard_name is None:
4400 match = guard_pattern.match(line)
4401 if match:
4402 guard_name = match.group(1)
4403 guard_line_number = line_number
4404
Daniel Bratell39b5b062018-05-16 18:09:574405 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454406 # don't match the chromium style guide, but new files should
4407 # get it right.
4408 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574409 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144410 errors.append(output_api.PresubmitPromptWarning(
4411 'Header using the wrong include guard name %s' % guard_name,
4412 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574413 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144414 else:
4415 # The line after #ifndef should have a #define of the same name.
4416 if line_number == guard_line_number + 1:
4417 expected_line = '#define %s' % guard_name
4418 if line != expected_line:
4419 errors.append(output_api.PresubmitPromptWarning(
4420 'Missing "%s" for include guard' % expected_line,
4421 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4422 'Expected: %r\nGot: %r' % (expected_line, line)))
4423
4424 if not seen_guard_end and line == '#endif // %s' % guard_name:
4425 seen_guard_end = True
4426 elif seen_guard_end:
4427 if line.strip() != '':
4428 errors.append(output_api.PresubmitPromptWarning(
4429 'Include guard %s not covering the whole file' % (
4430 guard_name), [f.LocalPath()]))
4431 break # Nothing else to check and enough to warn once.
4432
4433 if guard_name is None:
4434 errors.append(output_api.PresubmitPromptWarning(
4435 'Missing include guard %s' % expected_guard,
4436 [f.LocalPath()],
4437 'Missing include guard in %s\n'
4438 'Recommended name: %s\n'
4439 'This check can be disabled by having the string\n'
4440 'no-include-guard-because-multiply-included in the header.' %
4441 (f.LocalPath(), expected_guard)))
4442
4443 return errors
4444
4445
mostynbb639aca52015-01-07 20:31:234446def _CheckForWindowsLineEndings(input_api, output_api):
4447 """Check source code and known ascii text files for Windows style line
4448 endings.
4449 """
earthdok1b5e0ee2015-03-10 15:19:104450 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234451
4452 file_inclusion_pattern = (
4453 known_text_files,
4454 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4455 )
4456
mostynbb639aca52015-01-07 20:31:234457 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534458 source_file_filter = lambda f: input_api.FilterSourceFile(
4459 f, white_list=file_inclusion_pattern, black_list=None)
4460 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504461 include_file = False
4462 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234463 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504464 include_file = True
4465 if include_file:
4466 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234467
4468 if problems:
4469 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4470 'these files to contain Windows style line endings?\n' +
4471 '\n'.join(problems))]
4472
4473 return []
4474
4475
Vaclav Brozekd5de76a2018-03-17 07:57:504476def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134477 """Checks that all source files use SYSLOG properly."""
4478 syslog_files = []
4479 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564480 for line_number, line in f.ChangedContents():
4481 if 'SYSLOG' in line:
4482 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4483
pastarmovj89f7ee12016-09-20 14:58:134484 if syslog_files:
4485 return [output_api.PresubmitPromptWarning(
4486 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4487 ' calls.\nFiles to check:\n', items=syslog_files)]
4488 return []
4489
4490
[email protected]1f7b4172010-01-28 01:17:344491def CheckChangeOnUpload(input_api, output_api):
4492 results = []
4493 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474494 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284495 results.extend(
jam93a6ee792017-02-08 23:59:224496 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194497 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224498 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134499 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164500 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534501 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194502 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274503 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544504 return results
[email protected]ca8d1982009-02-19 16:33:124505
4506
[email protected]1bfb8322014-04-23 01:02:414507def GetTryServerMasterForBot(bot):
4508 """Returns the Try Server master for the given bot.
4509
[email protected]0bb112362014-07-26 04:38:324510 It tries to guess the master from the bot name, but may still fail
4511 and return None. There is no longer a default master.
4512 """
4513 # Potentially ambiguous bot names are listed explicitly.
4514 master_map = {
tandriie5587792016-07-14 00:34:504515 'chromium_presubmit': 'master.tryserver.chromium.linux',
4516 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414517 }
[email protected]0bb112362014-07-26 04:38:324518 master = master_map.get(bot)
4519 if not master:
wnwen4fbaab82016-05-25 12:54:364520 if 'android' in bot:
tandriie5587792016-07-14 00:34:504521 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364522 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504523 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324524 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504525 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324526 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504527 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324528 return master
[email protected]1bfb8322014-04-23 01:02:414529
4530
[email protected]ca8d1982009-02-19 16:33:124531def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544532 results = []
[email protected]1f7b4172010-01-28 01:17:344533 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574534 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544535 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274536 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344537 input_api,
4538 output_api,
[email protected]2fdd1f362013-01-16 03:56:034539 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274540
jam93a6ee792017-02-08 23:59:224541 results.extend(
4542 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544543 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4544 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384545 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4546 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414547 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4548 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544549 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144550
4551
4552def _CheckTranslationScreenshots(input_api, output_api):
4553 PART_FILE_TAG = "part"
4554 import os
4555 import sys
4556 from io import StringIO
4557
4558 try:
4559 old_sys_path = sys.path
4560 sys.path = sys.path + [input_api.os_path.join(
4561 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4562 import grit.grd_reader
4563 import grit.node.message
4564 import grit.util
4565 finally:
4566 sys.path = old_sys_path
4567
4568 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4569 """Load the grd file and return a dict of message ids to messages.
4570
4571 Ignores any nested grdp files pointed by <part> tag.
4572 """
4573 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4574 stop_after=None, first_ids_file=None,
Julian Pastarmov4f7af532019-07-17 19:25:374575 debug=False, defines={'_chromium': 1},
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144576 tags_to_ignore=set([PART_FILE_TAG]))
4577 return {
4578 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4579 grit.node.message.MessageNode)
4580 }
4581
4582 def _GetGrdpMessagesFromString(grdp_string):
4583 """Parses the contents of a grdp file given in grdp_string.
4584
4585 grd_reader can't parse grdp files directly. Instead, this creates a
4586 temporary directory with a grd file pointing to the grdp file, and loads the
4587 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4588 """
4589 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4590 <grit latest_public_release="1" current_release="1">
4591 <release seq="1">
4592 <messages>
4593 <part file="sub.grdp" />
4594 </messages>
4595 </release>
4596 </grit>
4597 """
4598 with grit.util.TempDir({'main.grd': WRAPPER,
4599 'sub.grdp': grdp_string}) as temp_dir:
4600 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4601
4602 new_or_added_paths = set(f.LocalPath()
4603 for f in input_api.AffectedFiles()
4604 if (f.Action() == 'A' or f.Action() == 'M'))
4605 removed_paths = set(f.LocalPath()
4606 for f in input_api.AffectedFiles(include_deletes=True)
4607 if f.Action() == 'D')
4608
4609 affected_grds = [f for f in input_api.AffectedFiles()
4610 if (f.LocalPath().endswith('.grd') or
4611 f.LocalPath().endswith('.grdp'))]
4612 affected_png_paths = [f.AbsoluteLocalPath()
4613 for f in input_api.AffectedFiles()
4614 if (f.LocalPath().endswith('.png'))]
4615
4616 # Check for screenshots. Developers can upload screenshots using
4617 # tools/translation/upload_screenshots.py which finds and uploads
4618 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4619 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4620 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4621 #
4622 # The logic here is as follows:
4623 #
4624 # - If the CL has a .png file under the screenshots directory for a grd
4625 # file, warn the developer. Actual images should never be checked into the
4626 # Chrome repo.
4627 #
4628 # - If the CL contains modified or new messages in grd files and doesn't
4629 # contain the corresponding .sha1 files, warn the developer to add images
4630 # and upload them via tools/translation/upload_screenshots.py.
4631 #
4632 # - If the CL contains modified or new messages in grd files and the
4633 # corresponding .sha1 files, everything looks good.
4634 #
4635 # - If the CL contains removed messages in grd files but the corresponding
4636 # .sha1 files aren't removed, warn the developer to remove them.
4637 unnecessary_screenshots = []
4638 missing_sha1 = []
4639 unnecessary_sha1_files = []
4640
4641
4642 def _CheckScreenshotAdded(screenshots_dir, message_id):
4643 sha1_path = input_api.os_path.join(
4644 screenshots_dir, message_id + '.png.sha1')
4645 if sha1_path not in new_or_added_paths:
4646 missing_sha1.append(sha1_path)
4647
4648
4649 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4650 sha1_path = input_api.os_path.join(
4651 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034652 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144653 unnecessary_sha1_files.append(sha1_path)
4654
4655
4656 for f in affected_grds:
4657 file_path = f.LocalPath()
4658 old_id_to_msg_map = {}
4659 new_id_to_msg_map = {}
4660 if file_path.endswith('.grdp'):
4661 if f.OldContents():
4662 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394663 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144664 if f.NewContents():
4665 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394666 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144667 else:
4668 if f.OldContents():
4669 old_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394670 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144671 if f.NewContents():
4672 new_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394673 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144674
4675 # Compute added, removed and modified message IDs.
4676 old_ids = set(old_id_to_msg_map)
4677 new_ids = set(new_id_to_msg_map)
4678 added_ids = new_ids - old_ids
4679 removed_ids = old_ids - new_ids
4680 modified_ids = set([])
4681 for key in old_ids.intersection(new_ids):
4682 if (old_id_to_msg_map[key].FormatXml()
4683 != new_id_to_msg_map[key].FormatXml()):
4684 modified_ids.add(key)
4685
4686 grd_name, ext = input_api.os_path.splitext(
4687 input_api.os_path.basename(file_path))
4688 screenshots_dir = input_api.os_path.join(
4689 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4690
4691 # Check the screenshot directory for .png files. Warn if there is any.
4692 for png_path in affected_png_paths:
4693 if png_path.startswith(screenshots_dir):
4694 unnecessary_screenshots.append(png_path)
4695
4696 for added_id in added_ids:
4697 _CheckScreenshotAdded(screenshots_dir, added_id)
4698
4699 for modified_id in modified_ids:
4700 _CheckScreenshotAdded(screenshots_dir, modified_id)
4701
4702 for removed_id in removed_ids:
4703 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4704
4705 results = []
4706 if unnecessary_screenshots:
4707 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394708 'Do not include actual screenshots in the changelist. Run '
4709 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144710 sorted(unnecessary_screenshots)))
4711
4712 if missing_sha1:
4713 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394714 'You are adding or modifying UI strings.\n'
4715 'To ensure the best translations, take screenshots of the relevant UI '
4716 '(https://g.co/chrome/translation) and add these files to your '
4717 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144718
4719 if unnecessary_sha1_files:
4720 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394721 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144722 sorted(unnecessary_sha1_files)))
4723
4724 return results