blob: 51abf03d32f13048d8b0d85440b142c8092444be [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$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332460 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042461 r"^ipc[\\/]ipc_logging\.cc$",
2462 r"^native_client_sdk[\\/]",
2463 r"^remoting[\\/]base[\\/]logging\.h$",
2464 r"^remoting[\\/]host[\\/].*",
2465 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062466 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332467 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042468 r"^tools[\\/]",
2469 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2470 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332471 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402472 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492473 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402474
thomasanderson625d3932017-03-29 07:16:582475 log_info = set([])
2476 printf = set([])
[email protected]85218562013-11-22 07:41:402477
2478 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582479 for _, line in f.ChangedContents():
2480 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2481 log_info.add(f.LocalPath())
2482 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2483 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372484
thomasanderson625d3932017-03-29 07:16:582485 if input_api.re.search(r"\bprintf\(", line):
2486 printf.add(f.LocalPath())
2487 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2488 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402489
2490 if log_info:
2491 return [output_api.PresubmitError(
2492 'These files spam the console log with LOG(INFO):',
2493 items=log_info)]
2494 if printf:
2495 return [output_api.PresubmitError(
2496 'These files spam the console log with printf/fprintf:',
2497 items=printf)]
2498 return []
2499
2500
[email protected]49aa76a2013-12-04 06:59:162501def _CheckForAnonymousVariables(input_api, output_api):
2502 """These types are all expected to hold locks while in scope and
2503 so should never be anonymous (which causes them to be immediately
2504 destroyed)."""
2505 they_who_must_be_named = [
2506 'base::AutoLock',
2507 'base::AutoReset',
2508 'base::AutoUnlock',
2509 'SkAutoAlphaRestore',
2510 'SkAutoBitmapShaderInstall',
2511 'SkAutoBlitterChoose',
2512 'SkAutoBounderCommit',
2513 'SkAutoCallProc',
2514 'SkAutoCanvasRestore',
2515 'SkAutoCommentBlock',
2516 'SkAutoDescriptor',
2517 'SkAutoDisableDirectionCheck',
2518 'SkAutoDisableOvalCheck',
2519 'SkAutoFree',
2520 'SkAutoGlyphCache',
2521 'SkAutoHDC',
2522 'SkAutoLockColors',
2523 'SkAutoLockPixels',
2524 'SkAutoMalloc',
2525 'SkAutoMaskFreeImage',
2526 'SkAutoMutexAcquire',
2527 'SkAutoPathBoundsUpdate',
2528 'SkAutoPDFRelease',
2529 'SkAutoRasterClipValidate',
2530 'SkAutoRef',
2531 'SkAutoTime',
2532 'SkAutoTrace',
2533 'SkAutoUnref',
2534 ]
2535 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2536 # bad: base::AutoLock(lock.get());
2537 # not bad: base::AutoLock lock(lock.get());
2538 bad_pattern = input_api.re.compile(anonymous)
2539 # good: new base::AutoLock(lock.get())
2540 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2541 errors = []
2542
2543 for f in input_api.AffectedFiles():
2544 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2545 continue
2546 for linenum, line in f.ChangedContents():
2547 if bad_pattern.search(line) and not good_pattern.search(line):
2548 errors.append('%s:%d' % (f.LocalPath(), linenum))
2549
2550 if errors:
2551 return [output_api.PresubmitError(
2552 'These lines create anonymous variables that need to be named:',
2553 items=errors)]
2554 return []
2555
2556
Peter Kasting4844e46e2018-02-23 07:27:102557def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532558 # Returns whether |template_str| is of the form <T, U...> for some types T
2559 # and U. Assumes that |template_str| is already in the form <...>.
2560 def HasMoreThanOneArg(template_str):
2561 # Level of <...> nesting.
2562 nesting = 0
2563 for c in template_str:
2564 if c == '<':
2565 nesting += 1
2566 elif c == '>':
2567 nesting -= 1
2568 elif c == ',' and nesting == 1:
2569 return True
2570 return False
2571
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492572 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102573 sources = lambda affected_file: input_api.FilterSourceFile(
2574 affected_file,
2575 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2576 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492577 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552578
2579 # Pattern to capture a single "<...>" block of template arguments. It can
2580 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2581 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2582 # latter would likely require counting that < and > match, which is not
2583 # expressible in regular languages. Should the need arise, one can introduce
2584 # limited counting (matching up to a total number of nesting depth), which
2585 # should cover all practical cases for already a low nesting limit.
2586 template_arg_pattern = (
2587 r'<[^>]*' # Opening block of <.
2588 r'>([^<]*>)?') # Closing block of >.
2589 # Prefix expressing that whatever follows is not already inside a <...>
2590 # block.
2591 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102592 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552593 not_inside_template_arg_pattern
2594 + r'\bstd::unique_ptr'
2595 + template_arg_pattern
2596 + r'\(\)')
2597
2598 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2599 template_arg_no_array_pattern = (
2600 r'<[^>]*[^]]' # Opening block of <.
2601 r'>([^(<]*[^]]>)?') # Closing block of >.
2602 # Prefix saying that what follows is the start of an expression.
2603 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2604 # Suffix saying that what follows are call parentheses with a non-empty list
2605 # of arguments.
2606 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532607 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552608 return_construct_pattern = input_api.re.compile(
2609 start_of_expr_pattern
2610 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532611 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552612 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532613 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552614 + nonempty_arg_list_pattern)
2615
Vaclav Brozek851d9602018-04-04 16:13:052616 problems_constructor = []
2617 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102618 for f in input_api.AffectedSourceFiles(sources):
2619 for line_number, line in f.ChangedContents():
2620 # Disallow:
2621 # return std::unique_ptr<T>(foo);
2622 # bar = std::unique_ptr<T>(foo);
2623 # But allow:
2624 # return std::unique_ptr<T[]>(foo);
2625 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532626 # And also allow cases when the second template argument is present. Those
2627 # cases cannot be handled by std::make_unique:
2628 # return std::unique_ptr<T, U>(foo);
2629 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052630 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532631 return_construct_result = return_construct_pattern.search(line)
2632 if return_construct_result and not HasMoreThanOneArg(
2633 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052634 problems_constructor.append(
2635 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102636 # Disallow:
2637 # std::unique_ptr<T>()
2638 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052639 problems_nullptr.append(
2640 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2641
2642 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162643 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052644 errors.append(output_api.PresubmitError(
2645 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162646 problems_nullptr))
2647 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052648 errors.append(output_api.PresubmitError(
2649 'The following files use explicit std::unique_ptr constructor.'
2650 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162651 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102652 return errors
2653
2654
[email protected]999261d2014-03-03 20:08:082655def _CheckUserActionUpdate(input_api, output_api):
2656 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522657 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082658 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522659 # If actions.xml is already included in the changelist, the PRESUBMIT
2660 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082661 return []
2662
[email protected]999261d2014-03-03 20:08:082663 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2664 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522665 current_actions = None
[email protected]999261d2014-03-03 20:08:082666 for f in input_api.AffectedFiles(file_filter=file_filter):
2667 for line_num, line in f.ChangedContents():
2668 match = input_api.re.search(action_re, line)
2669 if match:
[email protected]2f92dec2014-03-07 19:21:522670 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2671 # loaded only once.
2672 if not current_actions:
2673 with open('tools/metrics/actions/actions.xml') as actions_f:
2674 current_actions = actions_f.read()
2675 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082676 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522677 action = 'name="{0}"'.format(action_name)
2678 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082679 return [output_api.PresubmitPromptWarning(
2680 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522681 'tools/metrics/actions/actions.xml. Please run '
2682 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082683 % (f.LocalPath(), line_num, action_name))]
2684 return []
2685
2686
Daniel Cheng13ca61a882017-08-25 15:11:252687def _ImportJSONCommentEater(input_api):
2688 import sys
2689 sys.path = sys.path + [input_api.os_path.join(
2690 input_api.PresubmitLocalPath(),
2691 'tools', 'json_comment_eater')]
2692 import json_comment_eater
2693 return json_comment_eater
2694
2695
[email protected]99171a92014-06-03 08:44:472696def _GetJSONParseError(input_api, filename, eat_comments=True):
2697 try:
2698 contents = input_api.ReadFile(filename)
2699 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252700 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132701 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472702
2703 input_api.json.loads(contents)
2704 except ValueError as e:
2705 return e
2706 return None
2707
2708
2709def _GetIDLParseError(input_api, filename):
2710 try:
2711 contents = input_api.ReadFile(filename)
2712 idl_schema = input_api.os_path.join(
2713 input_api.PresubmitLocalPath(),
2714 'tools', 'json_schema_compiler', 'idl_schema.py')
2715 process = input_api.subprocess.Popen(
2716 [input_api.python_executable, idl_schema],
2717 stdin=input_api.subprocess.PIPE,
2718 stdout=input_api.subprocess.PIPE,
2719 stderr=input_api.subprocess.PIPE,
2720 universal_newlines=True)
2721 (_, error) = process.communicate(input=contents)
2722 return error or None
2723 except ValueError as e:
2724 return e
2725
2726
2727def _CheckParseErrors(input_api, output_api):
2728 """Check that IDL and JSON files do not contain syntax errors."""
2729 actions = {
2730 '.idl': _GetIDLParseError,
2731 '.json': _GetJSONParseError,
2732 }
[email protected]99171a92014-06-03 08:44:472733 # Most JSON files are preprocessed and support comments, but these do not.
2734 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042735 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472736 ]
2737 # Only run IDL checker on files in these directories.
2738 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042739 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2740 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472741 ]
2742
2743 def get_action(affected_file):
2744 filename = affected_file.LocalPath()
2745 return actions.get(input_api.os_path.splitext(filename)[1])
2746
[email protected]99171a92014-06-03 08:44:472747 def FilterFile(affected_file):
2748 action = get_action(affected_file)
2749 if not action:
2750 return False
2751 path = affected_file.LocalPath()
2752
Sean Kau46e29bc2017-08-28 16:31:162753 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472754 return False
2755
2756 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162757 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472758 return False
2759 return True
2760
2761 results = []
2762 for affected_file in input_api.AffectedFiles(
2763 file_filter=FilterFile, include_deletes=False):
2764 action = get_action(affected_file)
2765 kwargs = {}
2766 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162767 _MatchesFile(input_api, json_no_comments_patterns,
2768 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472769 kwargs['eat_comments'] = False
2770 parse_error = action(input_api,
2771 affected_file.AbsoluteLocalPath(),
2772 **kwargs)
2773 if parse_error:
2774 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2775 (affected_file.LocalPath(), parse_error)))
2776 return results
2777
2778
[email protected]760deea2013-12-10 19:33:492779def _CheckJavaStyle(input_api, output_api):
2780 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472781 import sys
[email protected]760deea2013-12-10 19:33:492782 original_sys_path = sys.path
2783 try:
2784 sys.path = sys.path + [input_api.os_path.join(
2785 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2786 import checkstyle
2787 finally:
2788 # Restore sys.path to what it was before.
2789 sys.path = original_sys_path
2790
2791 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092792 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512793 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492794
2795
Nate Fischerdfd9812e2019-07-18 22:03:002796def _CheckPythonDevilInit(input_api, output_api):
2797 """Checks to make sure devil is initialized correctly in python scripts."""
2798 script_common_initialize_pattern = input_api.re.compile(
2799 r'script_common\.InitializeEnvironment\(')
2800 devil_env_config_initialize = input_api.re.compile(
2801 r'devil_env\.config\.Initialize\(')
2802
2803 errors = []
2804
2805 sources = lambda affected_file: input_api.FilterSourceFile(
2806 affected_file,
2807 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2808 (r'^build[\\/]android[\\/]devil_chromium\.py',
2809 r'^third_party[\\/].*',)),
2810 white_list=[r'.*\.py$'])
2811
2812 for f in input_api.AffectedSourceFiles(sources):
2813 for line_num, line in f.ChangedContents():
2814 if (script_common_initialize_pattern.search(line) or
2815 devil_env_config_initialize.search(line)):
2816 errors.append("%s:%d" % (f.LocalPath(), line_num))
2817
2818 results = []
2819
2820 if errors:
2821 results.append(output_api.PresubmitError(
2822 'Devil initialization should always be done using '
2823 'devil_chromium.Initialize() in the chromium project, to use better '
2824 'defaults for dependencies (ex. up-to-date version of adb).',
2825 errors))
2826
2827 return results
2828
2829
Sean Kau46e29bc2017-08-28 16:31:162830def _MatchesFile(input_api, patterns, path):
2831 for pattern in patterns:
2832 if input_api.re.search(pattern, path):
2833 return True
2834 return False
2835
2836
Daniel Cheng7052cdf2017-11-21 19:23:292837def _GetOwnersFilesToCheckForIpcOwners(input_api):
2838 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172839
Daniel Cheng7052cdf2017-11-21 19:23:292840 Returns:
2841 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2842 contain to cover IPC-related files with noparent reviewer rules.
2843 """
2844 # Whether or not a file affects IPC is (mostly) determined by a simple list
2845 # of filename patterns.
dchenge07de812016-06-20 19:27:172846 file_patterns = [
palmerb19a0932017-01-24 04:00:312847 # Legacy IPC:
dchenge07de812016-06-20 19:27:172848 '*_messages.cc',
2849 '*_messages*.h',
2850 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312851 # Mojo IPC:
dchenge07de812016-06-20 19:27:172852 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472853 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172854 '*_struct_traits*.*',
2855 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312856 '*.typemap',
2857 # Android native IPC:
2858 '*.aidl',
2859 # Blink uses a different file naming convention:
2860 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472861 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172862 '*StructTraits*.*',
2863 '*TypeConverter*.*',
2864 ]
2865
scottmg7a6ed5ba2016-11-04 18:22:042866 # These third_party directories do not contain IPCs, but contain files
2867 # matching the above patterns, which trigger false positives.
2868 exclude_paths = [
2869 'third_party/crashpad/*',
Andres Medinae684cf42018-08-27 18:48:232870 'third_party/protobuf/benchmarks/python/*',
Daniel Chengebe635e2018-07-13 12:36:062871 'third_party/third_party/blink/renderer/platform/bindings/*',
Nico Weberee3dc9b2017-08-31 17:09:292872 'third_party/win_build_output/*',
Clark DuVallfb37334c2019-09-03 18:32:172873 # These aidl files are just used to communicate between class loaders
2874 # running in the same process.
2875 'weblayer/browser/java/org/chromium/weblayer_private/aidl/*',
scottmg7a6ed5ba2016-11-04 18:22:042876 ]
2877
dchenge07de812016-06-20 19:27:172878 # Dictionary mapping an OWNERS file path to Patterns.
2879 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2880 # rules ) to a PatternEntry.
2881 # PatternEntry is a dictionary with two keys:
2882 # - 'files': the files that are matched by this pattern
2883 # - 'rules': the per-file rules needed for this pattern
2884 # For example, if we expect OWNERS file to contain rules for *.mojom and
2885 # *_struct_traits*.*, Patterns might look like this:
2886 # {
2887 # '*.mojom': {
2888 # 'files': ...,
2889 # 'rules': [
2890 # 'per-file *.mojom=set noparent',
2891 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2892 # ],
2893 # },
2894 # '*_struct_traits*.*': {
2895 # 'files': ...,
2896 # 'rules': [
2897 # 'per-file *_struct_traits*.*=set noparent',
2898 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2899 # ],
2900 # },
2901 # }
2902 to_check = {}
2903
Daniel Cheng13ca61a882017-08-25 15:11:252904 def AddPatternToCheck(input_file, pattern):
2905 owners_file = input_api.os_path.join(
2906 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2907 if owners_file not in to_check:
2908 to_check[owners_file] = {}
2909 if pattern not in to_check[owners_file]:
2910 to_check[owners_file][pattern] = {
2911 'files': [],
2912 'rules': [
2913 'per-file %s=set noparent' % pattern,
2914 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2915 ]
2916 }
Vaclav Brozekd5de76a2018-03-17 07:57:502917 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252918
dchenge07de812016-06-20 19:27:172919 # Iterate through the affected files to see what we actually need to check
2920 # for. We should only nag patch authors about per-file rules if a file in that
2921 # directory would match that pattern. If a directory only contains *.mojom
2922 # files and no *_messages*.h files, we should only nag about rules for
2923 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252924 for f in input_api.AffectedFiles(include_deletes=False):
2925 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362926 # affected files for .json, .cc, and .h files which look like they contain
2927 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162928 if (f.LocalPath().endswith('.json') and
2929 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2930 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252931 json_comment_eater = _ImportJSONCommentEater(input_api)
2932 mostly_json_lines = '\n'.join(f.NewContents())
2933 # Comments aren't allowed in strict JSON, so filter them out.
2934 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432935 try:
2936 json_content = input_api.json.loads(json_lines)
2937 except:
2938 # There's another PRESUBMIT check that already verifies that JSON files
2939 # are not invalid, so no need to emit another warning here.
2940 continue
Daniel Cheng13ca61a882017-08-25 15:11:252941 if 'interface_provider_specs' in json_content:
2942 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362943 else:
2944 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2945 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2946 if (manifest_pattern.search(f.LocalPath()) and not
2947 test_manifest_pattern.search(f.LocalPath())):
2948 # We expect all actual service manifest files to contain at least one
2949 # qualified reference to service_manager::Manifest.
2950 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2951 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172952 for pattern in file_patterns:
2953 if input_api.fnmatch.fnmatch(
2954 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042955 skip = False
2956 for exclude in exclude_paths:
2957 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2958 skip = True
2959 break
2960 if skip:
2961 continue
Daniel Cheng13ca61a882017-08-25 15:11:252962 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172963 break
2964
Daniel Cheng7052cdf2017-11-21 19:23:292965 return to_check
2966
2967
2968def _CheckIpcOwners(input_api, output_api):
2969 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2970 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2971
2972 if to_check:
2973 # If there are any OWNERS files to check, there are IPC-related changes in
2974 # this CL. Auto-CC the review list.
2975 output_api.AppendCC('[email protected]')
2976
2977 # Go through the OWNERS files to check, filtering out rules that are already
2978 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172979 for owners_file, patterns in to_check.iteritems():
2980 try:
2981 with file(owners_file) as f:
2982 lines = set(f.read().splitlines())
2983 for entry in patterns.itervalues():
2984 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2985 ]
2986 except IOError:
2987 # No OWNERS file, so all the rules are definitely missing.
2988 continue
2989
2990 # All the remaining lines weren't found in OWNERS files, so emit an error.
2991 errors = []
2992 for owners_file, patterns in to_check.iteritems():
2993 missing_lines = []
2994 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502995 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172996 missing_lines.extend(entry['rules'])
2997 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2998 if missing_lines:
2999 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053000 'Because of the presence of files:\n%s\n\n'
3001 '%s needs the following %d lines added:\n\n%s' %
3002 ('\n'.join(files), owners_file, len(missing_lines),
3003 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173004
3005 results = []
3006 if errors:
vabrf5ce3bf92016-07-11 14:52:413007 if input_api.is_committing:
3008 output = output_api.PresubmitError
3009 else:
3010 output = output_api.PresubmitPromptWarning
3011 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593012 'Found OWNERS files that need to be updated for IPC security ' +
3013 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173014 long_text='\n\n'.join(errors)))
3015
3016 return results
3017
3018
jbriance9e12f162016-11-25 07:57:503019def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313020 """Checks that added or removed lines in non third party affected
3021 header files do not lead to new useless class or struct forward
3022 declaration.
jbriance9e12f162016-11-25 07:57:503023 """
3024 results = []
3025 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3026 input_api.re.MULTILINE)
3027 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3028 input_api.re.MULTILINE)
3029 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313030 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193031 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493032 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313033 continue
3034
jbriance9e12f162016-11-25 07:57:503035 if not f.LocalPath().endswith('.h'):
3036 continue
3037
3038 contents = input_api.ReadFile(f)
3039 fwd_decls = input_api.re.findall(class_pattern, contents)
3040 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3041
3042 useless_fwd_decls = []
3043 for decl in fwd_decls:
3044 count = sum(1 for _ in input_api.re.finditer(
3045 r'\b%s\b' % input_api.re.escape(decl), contents))
3046 if count == 1:
3047 useless_fwd_decls.append(decl)
3048
3049 if not useless_fwd_decls:
3050 continue
3051
3052 for line in f.GenerateScmDiff().splitlines():
3053 if (line.startswith('-') and not line.startswith('--') or
3054 line.startswith('+') and not line.startswith('++')):
3055 for decl in useless_fwd_decls:
3056 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3057 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243058 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503059 (f.LocalPath(), decl)))
3060 useless_fwd_decls.remove(decl)
3061
3062 return results
3063
Jinsong Fan91ebbbd2019-04-16 14:57:173064def _CheckAndroidDebuggableBuild(input_api, output_api):
3065 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3066 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3067 this is a debuggable build of Android.
3068 """
3069 build_type_check_pattern = input_api.re.compile(
3070 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3071
3072 errors = []
3073
3074 sources = lambda affected_file: input_api.FilterSourceFile(
3075 affected_file,
3076 black_list=(_EXCLUDED_PATHS +
3077 _TEST_CODE_EXCLUDED_PATHS +
3078 input_api.DEFAULT_BLACK_LIST +
3079 (r"^android_webview[\\/]support_library[\\/]"
3080 "boundary_interfaces[\\/]",
3081 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3082 r'^third_party[\\/].*',
3083 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3084 r"webview[\\/]chromium[\\/]License.*",)),
3085 white_list=[r'.*\.java$'])
3086
3087 for f in input_api.AffectedSourceFiles(sources):
3088 for line_num, line in f.ChangedContents():
3089 if build_type_check_pattern.search(line):
3090 errors.append("%s:%d" % (f.LocalPath(), line_num))
3091
3092 results = []
3093
3094 if errors:
3095 results.append(output_api.PresubmitPromptWarning(
3096 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3097 ' Please use BuildInfo.isDebugAndroid() instead.',
3098 errors))
3099
3100 return results
jbriance9e12f162016-11-25 07:57:503101
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493102# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293103def _CheckAndroidToastUsage(input_api, output_api):
3104 """Checks that code uses org.chromium.ui.widget.Toast instead of
3105 android.widget.Toast (Chromium Toast doesn't force hardware
3106 acceleration on low-end devices, saving memory).
3107 """
3108 toast_import_pattern = input_api.re.compile(
3109 r'^import android\.widget\.Toast;$')
3110
3111 errors = []
3112
3113 sources = lambda affected_file: input_api.FilterSourceFile(
3114 affected_file,
3115 black_list=(_EXCLUDED_PATHS +
3116 _TEST_CODE_EXCLUDED_PATHS +
3117 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043118 (r'^chromecast[\\/].*',
3119 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493120 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293121
3122 for f in input_api.AffectedSourceFiles(sources):
3123 for line_num, line in f.ChangedContents():
3124 if toast_import_pattern.search(line):
3125 errors.append("%s:%d" % (f.LocalPath(), line_num))
3126
3127 results = []
3128
3129 if errors:
3130 results.append(output_api.PresubmitError(
3131 'android.widget.Toast usage is detected. Android toasts use hardware'
3132 ' acceleration, and can be\ncostly on low-end devices. Please use'
3133 ' org.chromium.ui.widget.Toast instead.\n'
3134 'Contact [email protected] if you have any questions.',
3135 errors))
3136
3137 return results
3138
3139
dgnaa68d5e2015-06-10 10:08:223140def _CheckAndroidCrLogUsage(input_api, output_api):
3141 """Checks that new logs using org.chromium.base.Log:
3142 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513143 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223144 """
pkotwicza1dd0b002016-05-16 14:41:043145
torne89540622017-03-24 19:41:303146 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043147 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303148 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043149 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303150 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043151 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3152 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093153 # The customtabs_benchmark is a small app that does not depend on Chromium
3154 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043155 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043156 ]
3157
dgnaa68d5e2015-06-10 10:08:223158 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123159 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3160 class_in_base_pattern = input_api.re.compile(
3161 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3162 has_some_log_import_pattern = input_api.re.compile(
3163 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223164 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123165 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223166 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463167 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223168
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463169 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493170 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043171 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123172
dgnaa68d5e2015-06-10 10:08:223173 tag_decl_errors = []
3174 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123175 tag_errors = []
dgn38736db2015-09-18 19:20:513176 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123177 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223178
3179 for f in input_api.AffectedSourceFiles(sources):
3180 file_content = input_api.ReadFile(f)
3181 has_modified_logs = False
3182
3183 # Per line checks
dgn87d9fb62015-06-12 09:15:123184 if (cr_log_import_pattern.search(file_content) or
3185 (class_in_base_pattern.search(file_content) and
3186 not has_some_log_import_pattern.search(file_content))):
3187 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223188 for line_num, line in f.ChangedContents():
3189
3190 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123191 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223192 if match:
3193 has_modified_logs = True
3194
3195 # Make sure it uses "TAG"
3196 if not match.group('tag') == 'TAG':
3197 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123198 else:
3199 # Report non cr Log function calls in changed lines
3200 for line_num, line in f.ChangedContents():
3201 if log_call_pattern.search(line):
3202 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223203
3204 # Per file checks
3205 if has_modified_logs:
3206 # Make sure the tag is using the "cr" prefix and is not too long
3207 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513208 tag_name = match.group('name') if match else None
3209 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223210 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513211 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223212 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513213 elif '.' in tag_name:
3214 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223215
3216 results = []
3217 if tag_decl_errors:
3218 results.append(output_api.PresubmitPromptWarning(
3219 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513220 '"private static final String TAG = "<package tag>".\n'
3221 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223222 tag_decl_errors))
3223
3224 if tag_length_errors:
3225 results.append(output_api.PresubmitError(
3226 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513227 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223228 tag_length_errors))
3229
3230 if tag_errors:
3231 results.append(output_api.PresubmitPromptWarning(
3232 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3233 tag_errors))
3234
dgn87d9fb62015-06-12 09:15:123235 if util_log_errors:
dgn4401aa52015-04-29 16:26:173236 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123237 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3238 util_log_errors))
3239
dgn38736db2015-09-18 19:20:513240 if tag_with_dot_errors:
3241 results.append(output_api.PresubmitPromptWarning(
3242 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3243 tag_with_dot_errors))
3244
dgn4401aa52015-04-29 16:26:173245 return results
3246
3247
Yoland Yanb92fa522017-08-28 17:37:063248def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3249 """Checks that junit.framework.* is no longer used."""
3250 deprecated_junit_framework_pattern = input_api.re.compile(
3251 r'^import junit\.framework\..*;',
3252 input_api.re.MULTILINE)
3253 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493254 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063255 errors = []
3256 for f in input_api.AffectedFiles(sources):
3257 for line_num, line in f.ChangedContents():
3258 if deprecated_junit_framework_pattern.search(line):
3259 errors.append("%s:%d" % (f.LocalPath(), line_num))
3260
3261 results = []
3262 if errors:
3263 results.append(output_api.PresubmitError(
3264 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3265 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3266 ' if you have any question.', errors))
3267 return results
3268
3269
3270def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3271 """Checks that if new Java test classes have inheritance.
3272 Either the new test class is JUnit3 test or it is a JUnit4 test class
3273 with a base class, either case is undesirable.
3274 """
3275 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3276
3277 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493278 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063279 errors = []
3280 for f in input_api.AffectedFiles(sources):
3281 if not f.OldContents():
3282 class_declaration_start_flag = False
3283 for line_num, line in f.ChangedContents():
3284 if class_declaration_pattern.search(line):
3285 class_declaration_start_flag = True
3286 if class_declaration_start_flag and ' extends ' in line:
3287 errors.append('%s:%d' % (f.LocalPath(), line_num))
3288 if '{' in line:
3289 class_declaration_start_flag = False
3290
3291 results = []
3292 if errors:
3293 results.append(output_api.PresubmitPromptWarning(
3294 'The newly created files include Test classes that inherits from base'
3295 ' class. Please do not use inheritance in JUnit4 tests or add new'
3296 ' JUnit3 tests. Contact [email protected] if you have any'
3297 ' questions.', errors))
3298 return results
3299
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203300
yolandyan45001472016-12-21 21:12:423301def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3302 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3303 deprecated_annotation_import_pattern = input_api.re.compile(
3304 r'^import android\.test\.suitebuilder\.annotation\..*;',
3305 input_api.re.MULTILINE)
3306 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493307 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423308 errors = []
3309 for f in input_api.AffectedFiles(sources):
3310 for line_num, line in f.ChangedContents():
3311 if deprecated_annotation_import_pattern.search(line):
3312 errors.append("%s:%d" % (f.LocalPath(), line_num))
3313
3314 results = []
3315 if errors:
3316 results.append(output_api.PresubmitError(
3317 'Annotations in android.test.suitebuilder.annotation have been'
3318 ' deprecated since API level 24. Please use android.support.test.filters'
3319 ' from //third_party/android_support_test_runner:runner_java instead.'
3320 ' Contact [email protected] if you have any questions.', errors))
3321 return results
3322
3323
agrieve7b6479d82015-10-07 14:24:223324def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3325 """Checks if MDPI assets are placed in a correct directory."""
3326 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3327 ('/res/drawable/' in f.LocalPath() or
3328 '/res/drawable-ldrtl/' in f.LocalPath()))
3329 errors = []
3330 for f in input_api.AffectedFiles(include_deletes=False,
3331 file_filter=file_filter):
3332 errors.append(' %s' % f.LocalPath())
3333
3334 results = []
3335 if errors:
3336 results.append(output_api.PresubmitError(
3337 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3338 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3339 '/res/drawable-ldrtl/.\n'
3340 'Contact [email protected] if you have questions.', errors))
3341 return results
3342
3343
Nate Fischer535972b2017-09-16 01:06:183344def _CheckAndroidWebkitImports(input_api, output_api):
3345 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353346 android.webview.ValueCallback except in the WebView glue layer
3347 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183348 """
3349 valuecallback_import_pattern = input_api.re.compile(
3350 r'^import android\.webkit\.ValueCallback;$')
3351
3352 errors = []
3353
3354 sources = lambda affected_file: input_api.FilterSourceFile(
3355 affected_file,
3356 black_list=(_EXCLUDED_PATHS +
3357 _TEST_CODE_EXCLUDED_PATHS +
3358 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353359 (r'^android_webview[\\/]glue[\\/].*',
3360 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493361 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183362
3363 for f in input_api.AffectedSourceFiles(sources):
3364 for line_num, line in f.ChangedContents():
3365 if valuecallback_import_pattern.search(line):
3366 errors.append("%s:%d" % (f.LocalPath(), line_num))
3367
3368 results = []
3369
3370 if errors:
3371 results.append(output_api.PresubmitError(
3372 'android.webkit.ValueCallback usage is detected outside of the glue'
3373 ' layer. To stay compatible with the support library, android.webkit.*'
3374 ' classes should only be used inside the glue layer and'
3375 ' org.chromium.base.Callback should be used instead.',
3376 errors))
3377
3378 return results
3379
3380
Becky Zhou7c69b50992018-12-10 19:37:573381def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3382 """Checks Android XML styles """
3383 import sys
3384 original_sys_path = sys.path
3385 try:
3386 sys.path = sys.path + [input_api.os_path.join(
3387 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3388 import checkxmlstyle
3389 finally:
3390 # Restore sys.path to what it was before.
3391 sys.path = original_sys_path
3392
3393 if is_check_on_upload:
3394 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3395 else:
3396 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3397
3398
agrievef32bcc72016-04-04 14:57:403399class PydepsChecker(object):
3400 def __init__(self, input_api, pydeps_files):
3401 self._file_cache = {}
3402 self._input_api = input_api
3403 self._pydeps_files = pydeps_files
3404
3405 def _LoadFile(self, path):
3406 """Returns the list of paths within a .pydeps file relative to //."""
3407 if path not in self._file_cache:
3408 with open(path) as f:
3409 self._file_cache[path] = f.read()
3410 return self._file_cache[path]
3411
3412 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3413 """Returns an interable of paths within the .pydep, relativized to //."""
3414 os_path = self._input_api.os_path
3415 pydeps_dir = os_path.dirname(pydeps_path)
3416 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3417 if not l.startswith('*'))
3418 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3419
3420 def _CreateFilesToPydepsMap(self):
3421 """Returns a map of local_path -> list_of_pydeps."""
3422 ret = {}
3423 for pydep_local_path in self._pydeps_files:
3424 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3425 ret.setdefault(path, []).append(pydep_local_path)
3426 return ret
3427
3428 def ComputeAffectedPydeps(self):
3429 """Returns an iterable of .pydeps files that might need regenerating."""
3430 affected_pydeps = set()
3431 file_to_pydeps_map = None
3432 for f in self._input_api.AffectedFiles(include_deletes=True):
3433 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463434 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3435 # subrepositories. We can't figure out which files change, so re-check
3436 # all files.
3437 # Changes to print_python_deps.py affect all .pydeps.
3438 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403439 return self._pydeps_files
3440 elif local_path.endswith('.pydeps'):
3441 if local_path in self._pydeps_files:
3442 affected_pydeps.add(local_path)
3443 elif local_path.endswith('.py'):
3444 if file_to_pydeps_map is None:
3445 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3446 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3447 return affected_pydeps
3448
3449 def DetermineIfStale(self, pydeps_path):
3450 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413451 import difflib
John Budorick47ca3fe2018-02-10 00:53:103452 import os
3453
agrievef32bcc72016-04-04 14:57:403454 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3455 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103456 env = dict(os.environ)
3457 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403458 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103459 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413460 old_contents = old_pydeps_data[2:]
3461 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403462 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413463 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403464
3465
Tibor Goldschwendt360793f72019-06-25 18:23:493466def _ParseGclientArgs():
3467 args = {}
3468 with open('build/config/gclient_args.gni', 'r') as f:
3469 for line in f:
3470 line = line.strip()
3471 if not line or line.startswith('#'):
3472 continue
3473 attribute, value = line.split('=')
3474 args[attribute.strip()] = value.strip()
3475 return args
3476
3477
agrievef32bcc72016-04-04 14:57:403478def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3479 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403480 # This check is for Python dependency lists (.pydeps files), and involves
3481 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3482 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283483 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003484 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493485 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403486 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3487 results = []
3488 # First, check for new / deleted .pydeps.
3489 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033490 # Check whether we are running the presubmit check for a file in src.
3491 # f.LocalPath is relative to repo (src, or internal repo).
3492 # os_path.exists is relative to src repo.
3493 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3494 # to src and we can conclude that the pydeps is in src.
3495 if input_api.os_path.exists(f.LocalPath()):
3496 if f.LocalPath().endswith('.pydeps'):
3497 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3498 results.append(output_api.PresubmitError(
3499 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3500 'remove %s' % f.LocalPath()))
3501 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3502 results.append(output_api.PresubmitError(
3503 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3504 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403505
3506 if results:
3507 return results
3508
3509 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3510
3511 for pydep_path in checker.ComputeAffectedPydeps():
3512 try:
phajdan.jr0d9878552016-11-04 10:49:413513 result = checker.DetermineIfStale(pydep_path)
3514 if result:
3515 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403516 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413517 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3518 'To regenerate, run:\n\n %s' %
3519 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403520 except input_api.subprocess.CalledProcessError as error:
3521 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3522 long_text=error.output)]
3523
3524 return results
3525
3526
glidere61efad2015-02-18 17:39:433527def _CheckSingletonInHeaders(input_api, output_api):
3528 """Checks to make sure no header files have |Singleton<|."""
3529 def FileFilter(affected_file):
3530 # It's ok for base/memory/singleton.h to have |Singleton<|.
3531 black_list = (_EXCLUDED_PATHS +
3532 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043533 (r"^base[\\/]memory[\\/]singleton\.h$",
3534 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473535 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433536 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3537
sergeyu34d21222015-09-16 00:11:443538 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433539 files = []
3540 for f in input_api.AffectedSourceFiles(FileFilter):
3541 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3542 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3543 contents = input_api.ReadFile(f)
3544 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243545 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433546 pattern.search(line)):
3547 files.append(f)
3548 break
3549
3550 if files:
yolandyandaabc6d2016-04-18 18:29:393551 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443552 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433553 'Please move them to an appropriate source file so that the ' +
3554 'template gets instantiated in a single compilation unit.',
3555 files) ]
3556 return []
3557
3558
[email protected]fd20b902014-05-09 02:14:533559_DEPRECATED_CSS = [
3560 # Values
3561 ( "-webkit-box", "flex" ),
3562 ( "-webkit-inline-box", "inline-flex" ),
3563 ( "-webkit-flex", "flex" ),
3564 ( "-webkit-inline-flex", "inline-flex" ),
3565 ( "-webkit-min-content", "min-content" ),
3566 ( "-webkit-max-content", "max-content" ),
3567
3568 # Properties
3569 ( "-webkit-background-clip", "background-clip" ),
3570 ( "-webkit-background-origin", "background-origin" ),
3571 ( "-webkit-background-size", "background-size" ),
3572 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443573 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533574
3575 # Functions
3576 ( "-webkit-gradient", "gradient" ),
3577 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3578 ( "-webkit-linear-gradient", "linear-gradient" ),
3579 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3580 ( "-webkit-radial-gradient", "radial-gradient" ),
3581 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3582]
3583
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203584
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493585# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243586def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533587 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253588 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343589 documentation and iOS CSS for dom distiller
3590 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253591 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533592 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493593 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253594 black_list = (_EXCLUDED_PATHS +
3595 _TEST_CODE_EXCLUDED_PATHS +
3596 input_api.DEFAULT_BLACK_LIST +
3597 (r"^chrome/common/extensions/docs",
3598 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343599 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443600 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253601 r"^native_client_sdk"))
3602 file_filter = lambda f: input_api.FilterSourceFile(
3603 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533604 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3605 for line_num, line in fpath.ChangedContents():
3606 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023607 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533608 results.append(output_api.PresubmitError(
3609 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3610 (fpath.LocalPath(), line_num, deprecated_value, value)))
3611 return results
3612
mohan.reddyf21db962014-10-16 12:26:473613
rlanday6802cf632017-05-30 17:48:363614def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363615 bad_files = {}
3616 for f in input_api.AffectedFiles(include_deletes=False):
3617 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493618 not f.LocalPath().startswith('third_party/blink') and
3619 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363620 continue
3621
Daniel Bratell65b033262019-04-23 08:17:063622 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363623 continue
3624
Vaclav Brozekd5de76a2018-03-17 07:57:503625 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363626 if "#include" in line and "../" in line]
3627 if not relative_includes:
3628 continue
3629 bad_files[f.LocalPath()] = relative_includes
3630
3631 if not bad_files:
3632 return []
3633
3634 error_descriptions = []
3635 for file_path, bad_lines in bad_files.iteritems():
3636 error_description = file_path
3637 for line in bad_lines:
3638 error_description += '\n ' + line
3639 error_descriptions.append(error_description)
3640
3641 results = []
3642 results.append(output_api.PresubmitError(
3643 'You added one or more relative #include paths (including "../").\n'
3644 'These shouldn\'t be used because they can be used to include headers\n'
3645 'from code that\'s not correctly specified as a dependency in the\n'
3646 'relevant BUILD.gn file(s).',
3647 error_descriptions))
3648
3649 return results
3650
Takeshi Yoshinoe387aa32017-08-02 13:16:133651
Daniel Bratell65b033262019-04-23 08:17:063652def _CheckForCcIncludes(input_api, output_api):
3653 """Check that nobody tries to include a cc file. It's a relatively
3654 common error which results in duplicate symbols in object
3655 files. This may not always break the build until someone later gets
3656 very confusing linking errors."""
3657 results = []
3658 for f in input_api.AffectedFiles(include_deletes=False):
3659 # We let third_party code do whatever it wants
3660 if (f.LocalPath().startswith('third_party') and
3661 not f.LocalPath().startswith('third_party/blink') and
3662 not f.LocalPath().startswith('third_party\\blink')):
3663 continue
3664
3665 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3666 continue
3667
3668 for _, line in f.ChangedContents():
3669 if line.startswith('#include "'):
3670 included_file = line.split('"')[1]
3671 if _IsCPlusPlusFile(input_api, included_file):
3672 # The most common naming for external files with C++ code,
3673 # apart from standard headers, is to call them foo.inc, but
3674 # Chromium sometimes uses foo-inc.cc so allow that as well.
3675 if not included_file.endswith(('.h', '-inc.cc')):
3676 results.append(output_api.PresubmitError(
3677 'Only header files or .inc files should be included in other\n'
3678 'C++ files. Compiling the contents of a cc file more than once\n'
3679 'will cause duplicate information in the build which may later\n'
3680 'result in strange link_errors.\n' +
3681 f.LocalPath() + ':\n ' +
3682 line))
3683
3684 return results
3685
3686
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203687def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3688 if not isinstance(key, ast.Str):
3689 return 'Key at line %d must be a string literal' % key.lineno
3690 if not isinstance(value, ast.Dict):
3691 return 'Value at line %d must be a dict' % value.lineno
3692 if len(value.keys) != 1:
3693 return 'Dict at line %d must have single entry' % value.lineno
3694 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3695 return (
3696 'Entry at line %d must have a string literal \'filepath\' as key' %
3697 value.lineno)
3698 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133699
Takeshi Yoshinoe387aa32017-08-02 13:16:133700
Sergey Ulanov4af16052018-11-08 02:41:463701def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203702 if not isinstance(key, ast.Str):
3703 return 'Key at line %d must be a string literal' % key.lineno
3704 if not isinstance(value, ast.List):
3705 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463706 for element in value.elts:
3707 if not isinstance(element, ast.Str):
3708 return 'Watchlist elements on line %d is not a string' % key.lineno
3709 if not email_regex.match(element.s):
3710 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3711 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203712 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133713
Takeshi Yoshinoe387aa32017-08-02 13:16:133714
Sergey Ulanov4af16052018-11-08 02:41:463715def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203716 mismatch_template = (
3717 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3718 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133719
Sergey Ulanov4af16052018-11-08 02:41:463720 email_regex = input_api.re.compile(
3721 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3722
3723 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203724 i = 0
3725 last_key = ''
3726 while True:
3727 if i >= len(wd_dict.keys):
3728 if i >= len(w_dict.keys):
3729 return None
3730 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3731 elif i >= len(w_dict.keys):
3732 return (
3733 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133734
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203735 wd_key = wd_dict.keys[i]
3736 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133737
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203738 result = _CheckWatchlistDefinitionsEntrySyntax(
3739 wd_key, wd_dict.values[i], ast)
3740 if result is not None:
3741 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133742
Sergey Ulanov4af16052018-11-08 02:41:463743 result = _CheckWatchlistsEntrySyntax(
3744 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203745 if result is not None:
3746 return 'Bad entry in WATCHLISTS dict: %s' % result
3747
3748 if wd_key.s != w_key.s:
3749 return mismatch_template % (
3750 '%s at line %d' % (wd_key.s, wd_key.lineno),
3751 '%s at line %d' % (w_key.s, w_key.lineno))
3752
3753 if wd_key.s < last_key:
3754 return (
3755 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3756 (wd_key.lineno, w_key.lineno))
3757 last_key = wd_key.s
3758
3759 i = i + 1
3760
3761
Sergey Ulanov4af16052018-11-08 02:41:463762def _CheckWATCHLISTSSyntax(expression, input_api):
3763 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203764 if not isinstance(expression, ast.Expression):
3765 return 'WATCHLISTS file must contain a valid expression'
3766 dictionary = expression.body
3767 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3768 return 'WATCHLISTS file must have single dict with exactly two entries'
3769
3770 first_key = dictionary.keys[0]
3771 first_value = dictionary.values[0]
3772 second_key = dictionary.keys[1]
3773 second_value = dictionary.values[1]
3774
3775 if (not isinstance(first_key, ast.Str) or
3776 first_key.s != 'WATCHLIST_DEFINITIONS' or
3777 not isinstance(first_value, ast.Dict)):
3778 return (
3779 'The first entry of the dict in WATCHLISTS file must be '
3780 'WATCHLIST_DEFINITIONS dict')
3781
3782 if (not isinstance(second_key, ast.Str) or
3783 second_key.s != 'WATCHLISTS' or
3784 not isinstance(second_value, ast.Dict)):
3785 return (
3786 'The second entry of the dict in WATCHLISTS file must be '
3787 'WATCHLISTS dict')
3788
Sergey Ulanov4af16052018-11-08 02:41:463789 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133790
3791
3792def _CheckWATCHLISTS(input_api, output_api):
3793 for f in input_api.AffectedFiles(include_deletes=False):
3794 if f.LocalPath() == 'WATCHLISTS':
3795 contents = input_api.ReadFile(f, 'r')
3796
3797 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203798 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133799 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203800 # Get an AST tree for it and scan the tree for detailed style checking.
3801 expression = input_api.ast.parse(
3802 contents, filename='WATCHLISTS', mode='eval')
3803 except ValueError as e:
3804 return [output_api.PresubmitError(
3805 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3806 except SyntaxError as e:
3807 return [output_api.PresubmitError(
3808 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3809 except TypeError as e:
3810 return [output_api.PresubmitError(
3811 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133812
Sergey Ulanov4af16052018-11-08 02:41:463813 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203814 if result is not None:
3815 return [output_api.PresubmitError(result)]
3816 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133817
3818 return []
3819
3820
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193821def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3822 """Checks that newly added header files have corresponding GN changes.
3823 Note that this is only a heuristic. To be precise, run script:
3824 build/check_gn_headers.py.
3825 """
3826
3827 def headers(f):
3828 return input_api.FilterSourceFile(
3829 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3830
3831 new_headers = []
3832 for f in input_api.AffectedSourceFiles(headers):
3833 if f.Action() != 'A':
3834 continue
3835 new_headers.append(f.LocalPath())
3836
3837 def gn_files(f):
3838 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3839
3840 all_gn_changed_contents = ''
3841 for f in input_api.AffectedSourceFiles(gn_files):
3842 for _, line in f.ChangedContents():
3843 all_gn_changed_contents += line
3844
3845 problems = []
3846 for header in new_headers:
3847 basename = input_api.os_path.basename(header)
3848 if basename not in all_gn_changed_contents:
3849 problems.append(header)
3850
3851 if problems:
3852 return [output_api.PresubmitPromptWarning(
3853 'Missing GN changes for new header files', items=sorted(problems),
3854 long_text='Please double check whether newly added header files need '
3855 'corresponding changes in gn or gni files.\nThis checking is only a '
3856 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3857 'Read https://crbug.com/661774 for more info.')]
3858 return []
3859
3860
Michael Giuffridad3bc8672018-10-25 22:48:023861def _CheckCorrectProductNameInMessages(input_api, output_api):
3862 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3863
3864 This assumes we won't intentionally reference one product from the other
3865 product.
3866 """
3867 all_problems = []
3868 test_cases = [{
3869 "filename_postfix": "google_chrome_strings.grd",
3870 "correct_name": "Chrome",
3871 "incorrect_name": "Chromium",
3872 }, {
3873 "filename_postfix": "chromium_strings.grd",
3874 "correct_name": "Chromium",
3875 "incorrect_name": "Chrome",
3876 }]
3877
3878 for test_case in test_cases:
3879 problems = []
3880 filename_filter = lambda x: x.LocalPath().endswith(
3881 test_case["filename_postfix"])
3882
3883 # Check each new line. Can yield false positives in multiline comments, but
3884 # easier than trying to parse the XML because messages can have nested
3885 # children, and associating message elements with affected lines is hard.
3886 for f in input_api.AffectedSourceFiles(filename_filter):
3887 for line_num, line in f.ChangedContents():
3888 if "<message" in line or "<!--" in line or "-->" in line:
3889 continue
3890 if test_case["incorrect_name"] in line:
3891 problems.append(
3892 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3893
3894 if problems:
3895 message = (
3896 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3897 % (test_case["correct_name"], test_case["correct_name"],
3898 test_case["incorrect_name"]))
3899 all_problems.append(
3900 output_api.PresubmitPromptWarning(message, items=problems))
3901
3902 return all_problems
3903
3904
Dirk Pranke3c18a382019-03-15 01:07:513905def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3906 # TODO(crbug.com/941824): We need to make sure the entries in
3907 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3908 # so that users of //buildtools in other projects get the same tooling
3909 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3910 # support to gclient, we can eliminate the duplication and delete
3911 # this presubmit check.
3912
3913 # Update this regexp if new revisions are added to the files.
3914 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013915 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513916
3917 # If a user is changing one revision, they need to change the same
3918 # line in both files. This means that any given change should contain
3919 # exactly the same list of changed lines that match the regexps. The
3920 # replace(' ', '') call allows us to ignore whitespace changes to the
3921 # lines. The 'long_text' parameter to the error will contain the
3922 # list of changed lines in both files, which should make it easy enough
3923 # to spot the error without going overboard in this implementation.
3924 revs_changes = {
3925 'DEPS': {},
3926 'buildtools/DEPS': {},
3927 }
3928 long_text = ''
3929
3930 for f in input_api.AffectedFiles(
3931 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3932 for line_num, line in f.ChangedContents():
3933 if rev_regexp.search(line):
3934 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3935 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3936
3937 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3938 return [output_api.PresubmitError(
3939 'Change buildtools revisions in sync in both //DEPS and '
3940 '//buildtools/DEPS.', long_text=long_text + '\n')]
3941 else:
3942 return []
3943
3944
Daniel Bratell93eb6c62019-04-29 20:13:363945def _CheckForTooLargeFiles(input_api, output_api):
3946 """Avoid large files, especially binary files, in the repository since
3947 git doesn't scale well for those. They will be in everyone's repo
3948 clones forever, forever making Chromium slower to clone and work
3949 with."""
3950
3951 # Uploading files to cloud storage is not trivial so we don't want
3952 # to set the limit too low, but the upper limit for "normal" large
3953 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
3954 # anything over 20 MB is exceptional.
3955 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
3956
3957 too_large_files = []
3958 for f in input_api.AffectedFiles():
3959 # Check both added and modified files (but not deleted files).
3960 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:383961 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:363962 if size > TOO_LARGE_FILE_SIZE_LIMIT:
3963 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
3964
3965 if too_large_files:
3966 message = (
3967 'Do not commit large files to git since git scales badly for those.\n' +
3968 'Instead put the large files in cloud storage and use DEPS to\n' +
3969 'fetch them.\n' + '\n'.join(too_large_files)
3970 )
3971 return [output_api.PresubmitError(
3972 'Too large files found in commit', long_text=message + '\n')]
3973 else:
3974 return []
3975
Max Morozb47503b2019-08-08 21:03:273976
3977def _CheckFuzzTargets(input_api, output_api):
3978 """Checks specific for fuzz target sources."""
3979 EXPORTED_SYMBOLS = [
3980 'LLVMFuzzerInitialize',
3981 'LLVMFuzzerCustomMutator',
3982 'LLVMFuzzerCustomCrossOver',
3983 'LLVMFuzzerMutate',
3984 ]
3985
3986 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
3987
3988 def FilterFile(affected_file):
3989 """Ignore libFuzzer source code."""
3990 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
3991 black_list = r"^third_party[\\/]libFuzzer"
3992
3993 return input_api.FilterSourceFile(
3994 affected_file,
3995 white_list=[white_list],
3996 black_list=[black_list])
3997
3998 files_with_missing_header = []
3999 for f in input_api.AffectedSourceFiles(FilterFile):
4000 contents = input_api.ReadFile(f, 'r')
4001 if REQUIRED_HEADER in contents:
4002 continue
4003
4004 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4005 files_with_missing_header.append(f.LocalPath())
4006
4007 if not files_with_missing_header:
4008 return []
4009
4010 long_text = (
4011 'If you define any of the libFuzzer optional functions (%s), it is '
4012 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4013 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4014 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4015 'to access command line arguments passed to the fuzzer. Instead, prefer '
4016 'static initialization and shared resources as documented in '
4017 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4018 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4019 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4020 )
4021
4022 return [output_api.PresubmitPromptWarning(
4023 message="Missing '%s' in:" % REQUIRED_HEADER,
4024 items=files_with_missing_header,
4025 long_text=long_text)]
4026
4027
dgnaa68d5e2015-06-10 10:08:224028def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574029 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224030 results = []
dgnaa68d5e2015-06-10 10:08:224031 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174032 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224033 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294034 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064035 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4036 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424037 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184038 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574039 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
4040 return results
4041
4042def _AndroidSpecificOnCommitChecks(input_api, output_api):
4043 """Groups commit checks that target android code."""
4044 results = []
4045 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224046 return results
4047
4048
[email protected]22c9bd72011-03-27 16:47:394049def _CommonChecks(input_api, output_api):
4050 """Checks common to both upload and commit."""
4051 results = []
4052 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384053 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544054 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084055
4056 author = input_api.change.author_email
4057 if author and author not in _KNOWN_ROBOTS:
4058 results.extend(
4059 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4060
[email protected]55459852011-08-10 15:17:194061 results.extend(
[email protected]760deea2013-12-10 19:33:494062 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234063 results.extend(
4064 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544065 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184066 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344067 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524068 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224069 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444070 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594071 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314072 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064073 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124074 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184075 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224076 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304077 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494078 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034079 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494080 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444081 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274082 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074083 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544084 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444085 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394086 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554087 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044088 results.extend(
4089 input_api.canned_checks.CheckChangeHasNoTabs(
4090 input_api,
4091 output_api,
4092 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404093 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164094 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084095 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244096 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474097 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044098 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054099 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144100 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234101 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434102 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404103 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154104 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174105 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504106 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364107 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064108 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134109 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434110 results.extend(input_api.RunTests(
4111 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144112 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024113 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514114 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364115 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004116 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244117
Vaclav Brozekcdc7defb2018-03-20 09:54:354118 for f in input_api.AffectedFiles():
4119 path, name = input_api.os_path.split(f.LocalPath())
4120 if name == 'PRESUBMIT.py':
4121 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004122 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4123 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074124 # The PRESUBMIT.py file (and the directory containing it) might
4125 # have been affected by being moved or removed, so only try to
4126 # run the tests if they still exist.
4127 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4128 input_api, output_api, full_path,
4129 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394130 return results
[email protected]1f7b4172010-01-28 01:17:344131
[email protected]b337cb5b2011-01-23 21:24:054132
[email protected]b8079ae4a2012-12-05 19:56:494133def _CheckPatchFiles(input_api, output_api):
4134 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4135 if f.LocalPath().endswith(('.orig', '.rej'))]
4136 if problems:
4137 return [output_api.PresubmitError(
4138 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034139 else:
4140 return []
[email protected]b8079ae4a2012-12-05 19:56:494141
4142
Kent Tamura5a8755d2017-06-29 23:37:074143def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214144 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4145 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4146 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074147 include_re = input_api.re.compile(
4148 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4149 extension_re = input_api.re.compile(r'\.[a-z]+$')
4150 errors = []
4151 for f in input_api.AffectedFiles():
4152 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4153 continue
4154 found_line_number = None
4155 found_macro = None
4156 for line_num, line in f.ChangedContents():
4157 match = macro_re.search(line)
4158 if match:
4159 found_line_number = line_num
4160 found_macro = match.group(2)
4161 break
4162 if not found_line_number:
4163 continue
4164
4165 found_include = False
4166 for line in f.NewContents():
4167 if include_re.search(line):
4168 found_include = True
4169 break
4170 if found_include:
4171 continue
4172
4173 if not f.LocalPath().endswith('.h'):
4174 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4175 try:
4176 content = input_api.ReadFile(primary_header_path, 'r')
4177 if include_re.search(content):
4178 continue
4179 except IOError:
4180 pass
4181 errors.append('%s:%d %s macro is used without including build/'
4182 'build_config.h.'
4183 % (f.LocalPath(), found_line_number, found_macro))
4184 if errors:
4185 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4186 return []
4187
4188
[email protected]b00342e7f2013-03-26 16:21:544189def _DidYouMeanOSMacro(bad_macro):
4190 try:
4191 return {'A': 'OS_ANDROID',
4192 'B': 'OS_BSD',
4193 'C': 'OS_CHROMEOS',
4194 'F': 'OS_FREEBSD',
4195 'L': 'OS_LINUX',
4196 'M': 'OS_MACOSX',
4197 'N': 'OS_NACL',
4198 'O': 'OS_OPENBSD',
4199 'P': 'OS_POSIX',
4200 'S': 'OS_SOLARIS',
4201 'W': 'OS_WIN'}[bad_macro[3].upper()]
4202 except KeyError:
4203 return ''
4204
4205
4206def _CheckForInvalidOSMacrosInFile(input_api, f):
4207 """Check for sensible looking, totally invalid OS macros."""
4208 preprocessor_statement = input_api.re.compile(r'^\s*#')
4209 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4210 results = []
4211 for lnum, line in f.ChangedContents():
4212 if preprocessor_statement.search(line):
4213 for match in os_macro.finditer(line):
4214 if not match.group(1) in _VALID_OS_MACROS:
4215 good = _DidYouMeanOSMacro(match.group(1))
4216 did_you_mean = ' (did you mean %s?)' % good if good else ''
4217 results.append(' %s:%d %s%s' % (f.LocalPath(),
4218 lnum,
4219 match.group(1),
4220 did_you_mean))
4221 return results
4222
4223
4224def _CheckForInvalidOSMacros(input_api, output_api):
4225 """Check all affected files for invalid OS macros."""
4226 bad_macros = []
tzik3f295992018-12-04 20:32:234227 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474228 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544229 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4230
4231 if not bad_macros:
4232 return []
4233
4234 return [output_api.PresubmitError(
4235 'Possibly invalid OS macro[s] found. Please fix your code\n'
4236 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4237
lliabraa35bab3932014-10-01 12:16:444238
4239def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4240 """Check all affected files for invalid "if defined" macros."""
4241 ALWAYS_DEFINED_MACROS = (
4242 "TARGET_CPU_PPC",
4243 "TARGET_CPU_PPC64",
4244 "TARGET_CPU_68K",
4245 "TARGET_CPU_X86",
4246 "TARGET_CPU_ARM",
4247 "TARGET_CPU_MIPS",
4248 "TARGET_CPU_SPARC",
4249 "TARGET_CPU_ALPHA",
4250 "TARGET_IPHONE_SIMULATOR",
4251 "TARGET_OS_EMBEDDED",
4252 "TARGET_OS_IPHONE",
4253 "TARGET_OS_MAC",
4254 "TARGET_OS_UNIX",
4255 "TARGET_OS_WIN32",
4256 )
4257 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4258 results = []
4259 for lnum, line in f.ChangedContents():
4260 for match in ifdef_macro.finditer(line):
4261 if match.group(1) in ALWAYS_DEFINED_MACROS:
4262 always_defined = ' %s is always defined. ' % match.group(1)
4263 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4264 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4265 lnum,
4266 always_defined,
4267 did_you_mean))
4268 return results
4269
4270
4271def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4272 """Check all affected files for invalid "if defined" macros."""
4273 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054274 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444275 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054276 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214277 continue
lliabraa35bab3932014-10-01 12:16:444278 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4279 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4280
4281 if not bad_macros:
4282 return []
4283
4284 return [output_api.PresubmitError(
4285 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4286 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4287 bad_macros)]
4288
4289
mlamouria82272622014-09-16 18:45:044290def _CheckForIPCRules(input_api, output_api):
4291 """Check for same IPC rules described in
4292 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4293 """
4294 base_pattern = r'IPC_ENUM_TRAITS\('
4295 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4296 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4297
4298 problems = []
4299 for f in input_api.AffectedSourceFiles(None):
4300 local_path = f.LocalPath()
4301 if not local_path.endswith('.h'):
4302 continue
4303 for line_number, line in f.ChangedContents():
4304 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4305 problems.append(
4306 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4307
4308 if problems:
4309 return [output_api.PresubmitPromptWarning(
4310 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4311 else:
4312 return []
4313
[email protected]b00342e7f2013-03-26 16:21:544314
Stephen Martinis97a394142018-06-07 23:06:054315def _CheckForLongPathnames(input_api, output_api):
4316 """Check to make sure no files being submitted have long paths.
4317 This causes issues on Windows.
4318 """
4319 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194320 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054321 local_path = f.LocalPath()
4322 # Windows has a path limit of 260 characters. Limit path length to 200 so
4323 # that we have some extra for the prefix on dev machines and the bots.
4324 if len(local_path) > 200:
4325 problems.append(local_path)
4326
4327 if problems:
4328 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4329 else:
4330 return []
4331
4332
Daniel Bratell8ba52722018-03-02 16:06:144333def _CheckForIncludeGuards(input_api, output_api):
4334 """Check that header files have proper guards against multiple inclusion.
4335 If a file should not have such guards (and it probably should) then it
4336 should include the string "no-include-guard-because-multiply-included".
4337 """
Daniel Bratell6a75baef62018-06-04 10:04:454338 def is_chromium_header_file(f):
4339 # We only check header files under the control of the Chromium
4340 # project. That is, those outside third_party apart from
4341 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324342 # We also exclude *_message_generator.h headers as they use
4343 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454344 file_with_path = input_api.os_path.normpath(f.LocalPath())
4345 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324346 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454347 (not file_with_path.startswith('third_party') or
4348 file_with_path.startswith(
4349 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144350
4351 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344352 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144353
4354 errors = []
4355
Daniel Bratell6a75baef62018-06-04 10:04:454356 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144357 guard_name = None
4358 guard_line_number = None
4359 seen_guard_end = False
4360
4361 file_with_path = input_api.os_path.normpath(f.LocalPath())
4362 base_file_name = input_api.os_path.splitext(
4363 input_api.os_path.basename(file_with_path))[0]
4364 upper_base_file_name = base_file_name.upper()
4365
4366 expected_guard = replace_special_with_underscore(
4367 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144368
4369 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574370 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4371 # are too many (1000+) files with slight deviations from the
4372 # coding style. The most important part is that the include guard
4373 # is there, and that it's unique, not the name so this check is
4374 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144375 #
4376 # As code becomes more uniform, this could be made stricter.
4377
4378 guard_name_pattern_list = [
4379 # Anything with the right suffix (maybe with an extra _).
4380 r'\w+_H__?',
4381
Daniel Bratell39b5b062018-05-16 18:09:574382 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144383 r'\w+_h',
4384
4385 # Anything including the uppercase name of the file.
4386 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4387 upper_base_file_name)) + r'\w*',
4388 ]
4389 guard_name_pattern = '|'.join(guard_name_pattern_list)
4390 guard_pattern = input_api.re.compile(
4391 r'#ifndef\s+(' + guard_name_pattern + ')')
4392
4393 for line_number, line in enumerate(f.NewContents()):
4394 if 'no-include-guard-because-multiply-included' in line:
4395 guard_name = 'DUMMY' # To not trigger check outside the loop.
4396 break
4397
4398 if guard_name is None:
4399 match = guard_pattern.match(line)
4400 if match:
4401 guard_name = match.group(1)
4402 guard_line_number = line_number
4403
Daniel Bratell39b5b062018-05-16 18:09:574404 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454405 # don't match the chromium style guide, but new files should
4406 # get it right.
4407 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574408 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144409 errors.append(output_api.PresubmitPromptWarning(
4410 'Header using the wrong include guard name %s' % guard_name,
4411 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574412 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144413 else:
4414 # The line after #ifndef should have a #define of the same name.
4415 if line_number == guard_line_number + 1:
4416 expected_line = '#define %s' % guard_name
4417 if line != expected_line:
4418 errors.append(output_api.PresubmitPromptWarning(
4419 'Missing "%s" for include guard' % expected_line,
4420 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4421 'Expected: %r\nGot: %r' % (expected_line, line)))
4422
4423 if not seen_guard_end and line == '#endif // %s' % guard_name:
4424 seen_guard_end = True
4425 elif seen_guard_end:
4426 if line.strip() != '':
4427 errors.append(output_api.PresubmitPromptWarning(
4428 'Include guard %s not covering the whole file' % (
4429 guard_name), [f.LocalPath()]))
4430 break # Nothing else to check and enough to warn once.
4431
4432 if guard_name is None:
4433 errors.append(output_api.PresubmitPromptWarning(
4434 'Missing include guard %s' % expected_guard,
4435 [f.LocalPath()],
4436 'Missing include guard in %s\n'
4437 'Recommended name: %s\n'
4438 'This check can be disabled by having the string\n'
4439 'no-include-guard-because-multiply-included in the header.' %
4440 (f.LocalPath(), expected_guard)))
4441
4442 return errors
4443
4444
mostynbb639aca52015-01-07 20:31:234445def _CheckForWindowsLineEndings(input_api, output_api):
4446 """Check source code and known ascii text files for Windows style line
4447 endings.
4448 """
earthdok1b5e0ee2015-03-10 15:19:104449 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234450
4451 file_inclusion_pattern = (
4452 known_text_files,
4453 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4454 )
4455
mostynbb639aca52015-01-07 20:31:234456 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534457 source_file_filter = lambda f: input_api.FilterSourceFile(
4458 f, white_list=file_inclusion_pattern, black_list=None)
4459 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504460 include_file = False
4461 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234462 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504463 include_file = True
4464 if include_file:
4465 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234466
4467 if problems:
4468 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4469 'these files to contain Windows style line endings?\n' +
4470 '\n'.join(problems))]
4471
4472 return []
4473
4474
Vaclav Brozekd5de76a2018-03-17 07:57:504475def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134476 """Checks that all source files use SYSLOG properly."""
4477 syslog_files = []
4478 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564479 for line_number, line in f.ChangedContents():
4480 if 'SYSLOG' in line:
4481 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4482
pastarmovj89f7ee12016-09-20 14:58:134483 if syslog_files:
4484 return [output_api.PresubmitPromptWarning(
4485 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4486 ' calls.\nFiles to check:\n', items=syslog_files)]
4487 return []
4488
4489
[email protected]1f7b4172010-01-28 01:17:344490def CheckChangeOnUpload(input_api, output_api):
4491 results = []
4492 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474493 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284494 results.extend(
jam93a6ee792017-02-08 23:59:224495 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194496 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224497 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134498 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164499 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534500 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194501 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274502 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544503 return results
[email protected]ca8d1982009-02-19 16:33:124504
4505
[email protected]1bfb8322014-04-23 01:02:414506def GetTryServerMasterForBot(bot):
4507 """Returns the Try Server master for the given bot.
4508
[email protected]0bb112362014-07-26 04:38:324509 It tries to guess the master from the bot name, but may still fail
4510 and return None. There is no longer a default master.
4511 """
4512 # Potentially ambiguous bot names are listed explicitly.
4513 master_map = {
tandriie5587792016-07-14 00:34:504514 'chromium_presubmit': 'master.tryserver.chromium.linux',
4515 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414516 }
[email protected]0bb112362014-07-26 04:38:324517 master = master_map.get(bot)
4518 if not master:
wnwen4fbaab82016-05-25 12:54:364519 if 'android' in bot:
tandriie5587792016-07-14 00:34:504520 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364521 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504522 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324523 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504524 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324525 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504526 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324527 return master
[email protected]1bfb8322014-04-23 01:02:414528
4529
[email protected]ca8d1982009-02-19 16:33:124530def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544531 results = []
[email protected]1f7b4172010-01-28 01:17:344532 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574533 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544534 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274535 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344536 input_api,
4537 output_api,
[email protected]2fdd1f362013-01-16 03:56:034538 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274539
jam93a6ee792017-02-08 23:59:224540 results.extend(
4541 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544542 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4543 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384544 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4545 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414546 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4547 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544548 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144549
4550
4551def _CheckTranslationScreenshots(input_api, output_api):
4552 PART_FILE_TAG = "part"
4553 import os
4554 import sys
4555 from io import StringIO
4556
4557 try:
4558 old_sys_path = sys.path
4559 sys.path = sys.path + [input_api.os_path.join(
4560 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4561 import grit.grd_reader
4562 import grit.node.message
4563 import grit.util
4564 finally:
4565 sys.path = old_sys_path
4566
4567 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4568 """Load the grd file and return a dict of message ids to messages.
4569
4570 Ignores any nested grdp files pointed by <part> tag.
4571 """
4572 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4573 stop_after=None, first_ids_file=None,
Julian Pastarmov4f7af532019-07-17 19:25:374574 debug=False, defines={'_chromium': 1},
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144575 tags_to_ignore=set([PART_FILE_TAG]))
4576 return {
4577 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4578 grit.node.message.MessageNode)
4579 }
4580
4581 def _GetGrdpMessagesFromString(grdp_string):
4582 """Parses the contents of a grdp file given in grdp_string.
4583
4584 grd_reader can't parse grdp files directly. Instead, this creates a
4585 temporary directory with a grd file pointing to the grdp file, and loads the
4586 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4587 """
4588 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4589 <grit latest_public_release="1" current_release="1">
4590 <release seq="1">
4591 <messages>
4592 <part file="sub.grdp" />
4593 </messages>
4594 </release>
4595 </grit>
4596 """
4597 with grit.util.TempDir({'main.grd': WRAPPER,
4598 'sub.grdp': grdp_string}) as temp_dir:
4599 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4600
4601 new_or_added_paths = set(f.LocalPath()
4602 for f in input_api.AffectedFiles()
4603 if (f.Action() == 'A' or f.Action() == 'M'))
4604 removed_paths = set(f.LocalPath()
4605 for f in input_api.AffectedFiles(include_deletes=True)
4606 if f.Action() == 'D')
4607
4608 affected_grds = [f for f in input_api.AffectedFiles()
4609 if (f.LocalPath().endswith('.grd') or
4610 f.LocalPath().endswith('.grdp'))]
4611 affected_png_paths = [f.AbsoluteLocalPath()
4612 for f in input_api.AffectedFiles()
4613 if (f.LocalPath().endswith('.png'))]
4614
4615 # Check for screenshots. Developers can upload screenshots using
4616 # tools/translation/upload_screenshots.py which finds and uploads
4617 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4618 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4619 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4620 #
4621 # The logic here is as follows:
4622 #
4623 # - If the CL has a .png file under the screenshots directory for a grd
4624 # file, warn the developer. Actual images should never be checked into the
4625 # Chrome repo.
4626 #
4627 # - If the CL contains modified or new messages in grd files and doesn't
4628 # contain the corresponding .sha1 files, warn the developer to add images
4629 # and upload them via tools/translation/upload_screenshots.py.
4630 #
4631 # - If the CL contains modified or new messages in grd files and the
4632 # corresponding .sha1 files, everything looks good.
4633 #
4634 # - If the CL contains removed messages in grd files but the corresponding
4635 # .sha1 files aren't removed, warn the developer to remove them.
4636 unnecessary_screenshots = []
4637 missing_sha1 = []
4638 unnecessary_sha1_files = []
4639
4640
4641 def _CheckScreenshotAdded(screenshots_dir, message_id):
4642 sha1_path = input_api.os_path.join(
4643 screenshots_dir, message_id + '.png.sha1')
4644 if sha1_path not in new_or_added_paths:
4645 missing_sha1.append(sha1_path)
4646
4647
4648 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4649 sha1_path = input_api.os_path.join(
4650 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034651 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144652 unnecessary_sha1_files.append(sha1_path)
4653
4654
4655 for f in affected_grds:
4656 file_path = f.LocalPath()
4657 old_id_to_msg_map = {}
4658 new_id_to_msg_map = {}
4659 if file_path.endswith('.grdp'):
4660 if f.OldContents():
4661 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394662 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144663 if f.NewContents():
4664 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394665 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144666 else:
4667 if f.OldContents():
4668 old_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394669 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144670 if f.NewContents():
4671 new_id_to_msg_map = _GetGrdMessages(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394672 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144673
4674 # Compute added, removed and modified message IDs.
4675 old_ids = set(old_id_to_msg_map)
4676 new_ids = set(new_id_to_msg_map)
4677 added_ids = new_ids - old_ids
4678 removed_ids = old_ids - new_ids
4679 modified_ids = set([])
4680 for key in old_ids.intersection(new_ids):
4681 if (old_id_to_msg_map[key].FormatXml()
4682 != new_id_to_msg_map[key].FormatXml()):
4683 modified_ids.add(key)
4684
4685 grd_name, ext = input_api.os_path.splitext(
4686 input_api.os_path.basename(file_path))
4687 screenshots_dir = input_api.os_path.join(
4688 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4689
4690 # Check the screenshot directory for .png files. Warn if there is any.
4691 for png_path in affected_png_paths:
4692 if png_path.startswith(screenshots_dir):
4693 unnecessary_screenshots.append(png_path)
4694
4695 for added_id in added_ids:
4696 _CheckScreenshotAdded(screenshots_dir, added_id)
4697
4698 for modified_id in modified_ids:
4699 _CheckScreenshotAdded(screenshots_dir, modified_id)
4700
4701 for removed_id in removed_ids:
4702 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4703
4704 results = []
4705 if unnecessary_screenshots:
4706 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394707 'Do not include actual screenshots in the changelist. Run '
4708 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144709 sorted(unnecessary_screenshots)))
4710
4711 if missing_sha1:
4712 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394713 'You are adding or modifying UI strings.\n'
4714 'To ensure the best translations, take screenshots of the relevant UI '
4715 '(https://g.co/chrome/translation) and add these files to your '
4716 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144717
4718 if unnecessary_sha1_files:
4719 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394720 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144721 sorted(unnecessary_sha1_files)))
4722
4723 return results