blob: 48924f1b00fe5ffa51b67da641c1a75853e482a3 [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$",
Egor Paskoce145c42018-09-28 19:31:0428 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1429 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0430 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5431 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0432 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4033)
[email protected]ca8d1982009-02-19 16:33:1234
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Fragment of a regular expression that matches C++ and Objective-C++
37# implementation files.
38_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
39
wnwenbdc444e2016-05-25 13:44:1540
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1941# Fragment of a regular expression that matches C++ and Objective-C++
42# header files.
43_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
44
45
[email protected]06e6d0ff2012-12-11 01:36:4446# Regular expression that matches code only used for test binaries
47# (best effort).
48_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0449 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4450 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4451 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1252 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1853 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4454 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0455 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0556 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0457 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4758 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0459 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0860 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0461 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4162 # EarlGrey app side code for tests.
63 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4464)
[email protected]ca8d1982009-02-19 16:33:1265
Daniel Bratell609102be2019-03-27 20:53:2166_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1567
[email protected]eea609a2011-11-18 13:10:1268_TEST_ONLY_WARNING = (
69 'You might be calling functions intended only for testing from\n'
70 'production code. It is OK to ignore this warning if you know what\n'
71 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0772 'not perfect. The commit queue will not block on this warning,\n'
73 'however the android-binary-size trybot will block if the method\n'
74 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1275
76
[email protected]cf9b78f2012-11-14 11:40:2877_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4078 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2179 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
80 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2881
wnwenbdc444e2016-05-25 13:44:1582
Daniel Bratell609102be2019-03-27 20:53:2183# Format: Sequence of tuples containing:
84# * String pattern or, if starting with a slash, a regular expression.
85# * Sequence of strings to show when the pattern matches.
86# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:4187_BANNED_JAVA_FUNCTIONS = (
88 (
89 'StrictMode.allowThreadDiskReads()',
90 (
91 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
92 'directly.',
93 ),
94 False,
95 ),
96 (
97 'StrictMode.allowThreadDiskWrites()',
98 (
99 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
100 'directly.',
101 ),
102 False,
103 ),
104)
105
Daniel Bratell609102be2019-03-27 20:53:21106# Format: Sequence of tuples containing:
107# * String pattern or, if starting with a slash, a regular expression.
108# * Sequence of strings to show when the pattern matches.
109# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59110_BANNED_OBJC_FUNCTIONS = (
111 (
112 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20113 (
114 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59115 'prohibited. Please use CrTrackingArea instead.',
116 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
117 ),
118 False,
119 ),
120 (
[email protected]eaae1972014-04-16 04:17:26121 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20122 (
123 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59124 'instead.',
125 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
126 ),
127 False,
128 ),
129 (
130 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20131 (
132 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59133 'Please use |convertPoint:(point) fromView:nil| instead.',
134 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
135 ),
136 True,
137 ),
138 (
139 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20140 (
141 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59142 'Please use |convertPoint:(point) toView:nil| instead.',
143 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
144 ),
145 True,
146 ),
147 (
148 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20149 (
150 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59151 'Please use |convertRect:(point) fromView:nil| instead.',
152 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
153 ),
154 True,
155 ),
156 (
157 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20158 (
159 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59160 'Please use |convertRect:(point) toView:nil| instead.',
161 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
162 ),
163 True,
164 ),
165 (
166 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20167 (
168 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59169 'Please use |convertSize:(point) fromView:nil| instead.',
170 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
171 ),
172 True,
173 ),
174 (
175 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20176 (
177 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59178 'Please use |convertSize:(point) toView:nil| instead.',
179 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
180 ),
181 True,
182 ),
jif65398702016-10-27 10:19:48183 (
184 r"/\s+UTF8String\s*]",
185 (
186 'The use of -[NSString UTF8String] is dangerous as it can return null',
187 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
188 'Please use |SysNSStringToUTF8| instead.',
189 ),
190 True,
191 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34192 (
193 r'__unsafe_unretained',
194 (
195 'The use of __unsafe_unretained is almost certainly wrong, unless',
196 'when interacting with NSFastEnumeration or NSInvocation.',
197 'Please use __weak in files build with ARC, nothing otherwise.',
198 ),
199 False,
200 ),
Avi Drissman7382afa02019-04-29 23:27:13201 (
202 'freeWhenDone:NO',
203 (
204 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
205 'Foundation types is prohibited.',
206 ),
207 True,
208 ),
[email protected]127f18ec2012-06-16 05:05:59209)
210
Daniel Bratell609102be2019-03-27 20:53:21211# Format: Sequence of tuples containing:
212# * String pattern or, if starting with a slash, a regular expression.
213# * Sequence of strings to show when the pattern matches.
214# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54215_BANNED_IOS_OBJC_FUNCTIONS = (
216 (
217 r'/\bTEST[(]',
218 (
219 'TEST() macro should not be used in Objective-C++ code as it does not ',
220 'drain the autorelease pool at the end of the test. Use TEST_F() ',
221 'macro instead with a fixture inheriting from PlatformTest (or a ',
222 'typedef).'
223 ),
224 True,
225 ),
226 (
227 r'/\btesting::Test\b',
228 (
229 'testing::Test should not be used in Objective-C++ code as it does ',
230 'not drain the autorelease pool at the end of the test. Use ',
231 'PlatformTest instead.'
232 ),
233 True,
234 ),
235)
236
Peter K. Lee6c03ccff2019-07-15 14:40:05237# Format: Sequence of tuples containing:
238# * String pattern or, if starting with a slash, a regular expression.
239# * Sequence of strings to show when the pattern matches.
240# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
241_BANNED_IOS_EGTEST_FUNCTIONS = (
242 (
243 r'/\bEXPECT_OCMOCK_VERIFY\b',
244 (
245 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
246 'it is meant for GTests. Use [mock verify] instead.'
247 ),
248 True,
249 ),
250)
251
danakj7a2b7082019-05-21 21:13:51252# Directories that contain deprecated Bind() or Callback types.
253# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36254# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51255# echo "-- $i"
danakj710b4c02019-11-28 16:08:45256# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51257# done
258#
259# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
260# when they have been converted to modern callback types (OnceCallback,
261# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
262# checks for them and prevent regressions.
263_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
danakj7a2b7082019-05-21 21:13:51264 '^apps/',
danakj7a2b7082019-05-21 21:13:51265 '^base/callback.h', # Intentional.
266 '^chrome/app/',
267 '^chrome/browser/',
268 '^chrome/chrome_elf/',
269 '^chrome/chrome_watcher/',
270 '^chrome/common/',
271 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51272 '^chrome/renderer/',
273 '^chrome/services/',
274 '^chrome/test/',
275 '^chrome/tools/',
276 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51277 '^chromecast/media/',
278 '^chromecast/metrics/',
279 '^chromecast/net/',
280 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51281 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51282 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51283 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51284 '^components/arc/',
285 '^components/assist_ranker/',
286 '^components/autofill/',
287 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51288 '^components/browser_watcher/',
289 '^components/browsing_data/',
290 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51291 '^components/chromeos_camera/',
292 '^components/component_updater/',
293 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51294 '^components/cronet/',
295 '^components/data_reduction_proxy/',
296 '^components/discardable_memory/',
danakj7a2b7082019-05-21 21:13:51297 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36298 '^components/dom_distiller/',
danakj7a2b7082019-05-21 21:13:51299 '^components/download/',
300 '^components/drive/',
301 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51302 '^components/feature_engagement/',
303 '^components/feedback/',
304 '^components/flags_ui/',
305 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51306 '^components/guest_view/',
307 '^components/heap_profiling/',
308 '^components/history/',
309 '^components/image_fetcher/',
310 '^components/invalidation/',
311 '^components/keyed_service/',
312 '^components/login/',
313 '^components/metrics/',
314 '^components/metrics_services_manager/',
315 '^components/nacl/',
316 '^components/navigation_interception/',
317 '^components/net_log/',
318 '^components/network_time/',
319 '^components/ntp_snippets/',
320 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51321 '^components/offline_pages/',
322 '^components/omnibox/',
323 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51324 '^components/password_manager/',
325 '^components/payments/',
326 '^components/plugins/',
327 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51328 '^components/proxy_config/',
329 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51330 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51331 '^components/rlz/',
332 '^components/safe_browsing/',
333 '^components/search_engines/',
334 '^components/search_provider_logos/',
335 '^components/security_interstitials/',
336 '^components/security_state/',
337 '^components/services/',
338 '^components/sessions/',
339 '^components/signin/',
340 '^components/ssl_errors/',
341 '^components/storage_monitor/',
342 '^components/subresource_filter/',
343 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51344 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51345 '^components/sync_preferences/',
346 '^components/sync_sessions/',
347 '^components/test/',
348 '^components/tracing/',
349 '^components/translate/',
350 '^components/ukm/',
351 '^components/update_client/',
352 '^components/upload_list/',
353 '^components/variations/',
354 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51355 '^components/webcrypto/',
356 '^components/webdata/',
357 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51358 '^device/bluetooth/',
danakj7a2b7082019-05-21 21:13:51359 '^extensions/',
danakj7a2b7082019-05-21 21:13:51360 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51361 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51362 '^ios/chrome/',
363 '^ios/components/',
364 '^ios/net/',
365 '^ios/web/',
366 '^ios/web_view/',
367 '^ipc/',
368 '^media/audio/',
369 '^media/base/',
danakjc8576092019-11-26 19:01:36370 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51371 '^media/capture/',
372 '^media/cast/',
373 '^media/cdm/',
374 '^media/device_monitors/',
375 '^media/ffmpeg/',
376 '^media/filters/',
377 '^media/formats/',
378 '^media/gpu/',
379 '^media/mojo/',
380 '^media/muxers/',
381 '^media/remoting/',
382 '^media/renderers/',
383 '^media/test/',
danakj7a2b7082019-05-21 21:13:51384 '^net/',
385 '^ppapi/proxy/',
386 '^ppapi/shared_impl/',
387 '^ppapi/tests/',
388 '^ppapi/thunk/',
389 '^remoting/base/',
390 '^remoting/client/',
391 '^remoting/codec/',
392 '^remoting/host/',
393 '^remoting/internal/',
394 '^remoting/ios/',
395 '^remoting/protocol/',
396 '^remoting/signaling/',
397 '^remoting/test/',
danakj7a2b7082019-05-21 21:13:51398 '^services/',
danakj7a2b7082019-05-21 21:13:51399 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51400 '^tools/clang/base_bind_rewriters/', # Intentional.
401 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51402))
[email protected]127f18ec2012-06-16 05:05:59403
Daniel Bratell609102be2019-03-27 20:53:21404# Format: Sequence of tuples containing:
405# * String pattern or, if starting with a slash, a regular expression.
406# * Sequence of strings to show when the pattern matches.
407# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
408# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59409_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20410 (
Dave Tapuska98199b612019-07-10 13:30:44411 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53412 (
413 'New code should not use NULL. Use nullptr instead.',
414 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20415 False,
thomasandersone7caaa9b2017-03-29 19:22:53416 (),
417 ),
Peter Kasting94a56c42019-10-25 21:54:04418 (
419 r'/\busing namespace ',
420 (
421 'Using directives ("using namespace x") are banned by the Google Style',
422 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
423 'Explicitly qualify symbols or use using declarations ("using x::foo").',
424 ),
425 True,
426 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
427 ),
Antonio Gomes07300d02019-03-13 20:59:57428 # Make sure that gtest's FRIEND_TEST() macro is not used; the
429 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
430 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53431 (
[email protected]23e6cbc2012-06-16 18:51:20432 'FRIEND_TEST(',
433 (
[email protected]e3c945502012-06-26 20:01:49434 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20435 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
436 ),
437 False,
[email protected]7345da02012-11-27 14:31:49438 (),
[email protected]23e6cbc2012-06-16 18:51:20439 ),
440 (
Dave Tapuska98199b612019-07-10 13:30:44441 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53442 (
443 'Chrome clients wishing to select events on X windows should use',
444 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
445 'you are selecting events from the GPU process, or if you are using',
446 'an XDisplay other than gfx::GetXDisplay().',
447 ),
448 True,
449 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40450 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04451 r"^ui[\\/]gl[\\/].*\.cc$",
452 r"^media[\\/]gpu[\\/].*\.cc$",
453 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53454 ),
455 ),
456 (
Dave Tapuska98199b612019-07-10 13:30:44457 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20458 (
thomasanderson11aa41d2017-06-08 22:22:38459 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20460 ),
461 True,
462 (
Egor Paskoce145c42018-09-28 19:31:04463 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
464 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
465 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20466 ),
467 ),
468 (
tomhudsone2c14d552016-05-26 17:07:46469 'setMatrixClip',
470 (
471 'Overriding setMatrixClip() is prohibited; ',
472 'the base function is deprecated. ',
473 ),
474 True,
475 (),
476 ),
477 (
[email protected]52657f62013-05-20 05:30:31478 'SkRefPtr',
479 (
480 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22481 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31482 ),
483 True,
484 (),
485 ),
486 (
487 'SkAutoRef',
488 (
489 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22490 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31491 ),
492 True,
493 (),
494 ),
495 (
496 'SkAutoTUnref',
497 (
498 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22499 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31500 ),
501 True,
502 (),
503 ),
504 (
505 'SkAutoUnref',
506 (
507 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
508 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22509 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31510 ),
511 True,
512 (),
513 ),
[email protected]d89eec82013-12-03 14:10:59514 (
515 r'/HANDLE_EINTR\(.*close',
516 (
517 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
518 'descriptor will be closed, and it is incorrect to retry the close.',
519 'Either call close directly and ignore its return value, or wrap close',
520 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
521 ),
522 True,
523 (),
524 ),
525 (
526 r'/IGNORE_EINTR\((?!.*close)',
527 (
528 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
529 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
530 ),
531 True,
532 (
533 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04534 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
535 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59536 ),
537 ),
[email protected]ec5b3f02014-04-04 18:43:43538 (
539 r'/v8::Extension\(',
540 (
541 'Do not introduce new v8::Extensions into the code base, use',
542 'gin::Wrappable instead. See http://crbug.com/334679',
543 ),
544 True,
[email protected]f55c90ee62014-04-12 00:50:03545 (
Egor Paskoce145c42018-09-28 19:31:04546 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03547 ),
[email protected]ec5b3f02014-04-04 18:43:43548 ),
skyostilf9469f72015-04-20 10:38:52549 (
jame2d1a952016-04-02 00:27:10550 '#pragma comment(lib,',
551 (
552 'Specify libraries to link with in build files and not in the source.',
553 ),
554 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41555 (
tzik3f295992018-12-04 20:32:23556 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04557 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41558 ),
jame2d1a952016-04-02 00:27:10559 ),
fdorayc4ac18d2017-05-01 21:39:59560 (
Gabriel Charette7cc6c432018-04-25 20:52:02561 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59562 (
563 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
564 ),
565 False,
566 (),
567 ),
568 (
Gabriel Charette7cc6c432018-04-25 20:52:02569 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59570 (
571 'Consider using THREAD_CHECKER macros instead of the class directly.',
572 ),
573 False,
574 (),
575 ),
dbeamb6f4fde2017-06-15 04:03:06576 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06577 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
578 (
579 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
580 'deprecated (http://crbug.com/634507). Please avoid converting away',
581 'from the Time types in Chromium code, especially if any math is',
582 'being done on time values. For interfacing with platform/library',
583 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
584 'type converter methods instead. For faking TimeXXX values (for unit',
585 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
586 'other use cases, please contact base/time/OWNERS.',
587 ),
588 False,
589 (),
590 ),
591 (
dbeamb6f4fde2017-06-15 04:03:06592 'CallJavascriptFunctionUnsafe',
593 (
594 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
595 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
596 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
597 ),
598 False,
599 (
Egor Paskoce145c42018-09-28 19:31:04600 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
601 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
602 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06603 ),
604 ),
dskiba1474c2bfd62017-07-20 02:19:24605 (
606 'leveldb::DB::Open',
607 (
608 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
609 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
610 "Chrome's tracing, making their memory usage visible.",
611 ),
612 True,
613 (
614 r'^third_party/leveldatabase/.*\.(cc|h)$',
615 ),
Gabriel Charette0592c3a2017-07-26 12:02:04616 ),
617 (
Chris Mumfordc38afb62017-10-09 17:55:08618 'leveldb::NewMemEnv',
619 (
620 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58621 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
622 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08623 ),
624 True,
625 (
626 r'^third_party/leveldatabase/.*\.(cc|h)$',
627 ),
628 ),
629 (
Gabriel Charetted9839bc2017-07-29 14:17:47630 'RunLoop::QuitCurrent',
631 (
Robert Liao64b7ab22017-08-04 23:03:43632 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
633 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47634 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41635 False,
Gabriel Charetted9839bc2017-07-29 14:17:47636 (),
Gabriel Charettea44975052017-08-21 23:14:04637 ),
638 (
639 'base::ScopedMockTimeMessageLoopTaskRunner',
640 (
Gabriel Charette87cc1af2018-04-25 20:52:51641 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11642 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51643 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
644 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
645 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04646 ),
Gabriel Charette87cc1af2018-04-25 20:52:51647 False,
Gabriel Charettea44975052017-08-21 23:14:04648 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57649 ),
650 (
Dave Tapuska98199b612019-07-10 13:30:44651 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57652 (
653 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02654 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57655 ),
656 True,
657 (),
Francois Doray43670e32017-09-27 12:40:38658 ),
659 (
Peter Kasting991618a62019-06-17 22:00:09660 r'/\bstd::stoi\b',
661 (
662 'std::stoi uses exceptions to communicate results. ',
663 'Use base::StringToInt() instead.',
664 ),
665 True,
666 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
667 ),
668 (
669 r'/\bstd::stol\b',
670 (
671 'std::stol uses exceptions to communicate results. ',
672 'Use base::StringToInt() instead.',
673 ),
674 True,
675 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
676 ),
677 (
678 r'/\bstd::stoul\b',
679 (
680 'std::stoul uses exceptions to communicate results. ',
681 'Use base::StringToUint() instead.',
682 ),
683 True,
684 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
685 ),
686 (
687 r'/\bstd::stoll\b',
688 (
689 'std::stoll uses exceptions to communicate results. ',
690 'Use base::StringToInt64() instead.',
691 ),
692 True,
693 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
694 ),
695 (
696 r'/\bstd::stoull\b',
697 (
698 'std::stoull uses exceptions to communicate results. ',
699 'Use base::StringToUint64() instead.',
700 ),
701 True,
702 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
703 ),
704 (
705 r'/\bstd::stof\b',
706 (
707 'std::stof uses exceptions to communicate results. ',
708 'For locale-independent values, e.g. reading numbers from disk',
709 'profiles, use base::StringToDouble().',
710 'For user-visible values, parse using ICU.',
711 ),
712 True,
713 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
714 ),
715 (
716 r'/\bstd::stod\b',
717 (
718 'std::stod uses exceptions to communicate results. ',
719 'For locale-independent values, e.g. reading numbers from disk',
720 'profiles, use base::StringToDouble().',
721 'For user-visible values, parse using ICU.',
722 ),
723 True,
724 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
725 ),
726 (
727 r'/\bstd::stold\b',
728 (
729 'std::stold uses exceptions to communicate results. ',
730 'For locale-independent values, e.g. reading numbers from disk',
731 'profiles, use base::StringToDouble().',
732 'For user-visible values, parse using ICU.',
733 ),
734 True,
735 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
736 ),
737 (
Daniel Bratell69334cc2019-03-26 11:07:45738 r'/\bstd::to_string\b',
739 (
740 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09741 'For locale-independent strings, e.g. writing numbers to disk',
742 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45743 'For user-visible strings, use base::FormatNumber() and',
744 'the related functions in base/i18n/number_formatting.h.',
745 ),
Peter Kasting991618a62019-06-17 22:00:09746 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21747 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45748 ),
749 (
750 r'/\bstd::shared_ptr\b',
751 (
752 'std::shared_ptr should not be used. Use scoped_refptr instead.',
753 ),
754 True,
Andreas Haas63f58792019-11-07 10:56:44755 [_THIRD_PARTY_EXCEPT_BLINK,
756 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
757 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21758 ),
759 (
Peter Kasting991618a62019-06-17 22:00:09760 r'/\bstd::weak_ptr\b',
761 (
762 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
763 ),
764 True,
765 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
766 ),
767 (
Daniel Bratell609102be2019-03-27 20:53:21768 r'/\blong long\b',
769 (
770 'long long is banned. Use stdint.h if you need a 64 bit number.',
771 ),
772 False, # Only a warning since it is already used.
773 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
774 ),
775 (
776 r'/\bstd::bind\b',
777 (
778 'std::bind is banned because of lifetime risks.',
779 'Use base::BindOnce or base::BindRepeating instead.',
780 ),
781 True,
782 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
783 ),
784 (
785 r'/\b#include <chrono>\b',
786 (
787 '<chrono> overlaps with Time APIs in base. Keep using',
788 'base classes.',
789 ),
790 True,
791 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
792 ),
793 (
794 r'/\b#include <exception>\b',
795 (
796 'Exceptions are banned and disabled in Chromium.',
797 ),
798 True,
799 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
800 ),
801 (
802 r'/\bstd::function\b',
803 (
804 'std::function is banned. Instead use base::Callback which directly',
805 'supports Chromium\'s weak pointers, ref counting and more.',
806 ),
Peter Kasting991618a62019-06-17 22:00:09807 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21808 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
809 ),
810 (
811 r'/\b#include <random>\b',
812 (
813 'Do not use any random number engines from <random>. Instead',
814 'use base::RandomBitGenerator.',
815 ),
816 True,
817 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
818 ),
819 (
820 r'/\bstd::ratio\b',
821 (
822 'std::ratio is banned by the Google Style Guide.',
823 ),
824 True,
825 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45826 ),
827 (
Francois Doray43670e32017-09-27 12:40:38828 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
829 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
830 (
831 'Use the new API in base/threading/thread_restrictions.h.',
832 ),
Gabriel Charette04b138f2018-08-06 00:03:22833 False,
Francois Doray43670e32017-09-27 12:40:38834 (),
835 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38836 (
danakj7a2b7082019-05-21 21:13:51837 r'/\bbase::Bind\(',
838 (
839 'Please use base::Bind{Once,Repeating} instead',
840 'of base::Bind. (crbug.com/714018)',
841 ),
842 False,
Erik Staaba737d7602019-11-25 18:41:07843 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51844 ),
845 (
846 r'/\bbase::Callback[<:]',
847 (
848 'Please use base::{Once,Repeating}Callback instead',
849 'of base::Callback. (crbug.com/714018)',
850 ),
851 False,
Erik Staaba737d7602019-11-25 18:41:07852 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51853 ),
854 (
855 r'/\bbase::Closure\b',
856 (
857 'Please use base::{Once,Repeating}Closure instead',
858 'of base::Closure. (crbug.com/714018)',
859 ),
860 False,
Erik Staaba737d7602019-11-25 18:41:07861 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51862 ),
863 (
Michael Giuffrida7f93d6922019-04-19 14:39:58864 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19865 (
866 'RunMessageLoop is deprecated, use RunLoop instead.',
867 ),
868 False,
869 (),
870 ),
871 (
Dave Tapuska98199b612019-07-10 13:30:44872 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19873 (
874 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
875 ),
876 False,
877 (),
878 ),
879 (
Dave Tapuska98199b612019-07-10 13:30:44880 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19881 (
882 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
883 "if you're convinced you need this.",
884 ),
885 False,
886 (),
887 ),
888 (
Dave Tapuska98199b612019-07-10 13:30:44889 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19890 (
891 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04892 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19893 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
894 'async events instead of flushing threads.',
895 ),
896 False,
897 (),
898 ),
899 (
900 r'MessageLoopRunner',
901 (
902 'MessageLoopRunner is deprecated, use RunLoop instead.',
903 ),
904 False,
905 (),
906 ),
907 (
Dave Tapuska98199b612019-07-10 13:30:44908 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19909 (
910 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
911 "gab@ if you found a use case where this is the only solution.",
912 ),
913 False,
914 (),
915 ),
916 (
Victor Costane48a2e82019-03-15 22:02:34917 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16918 (
Victor Costane48a2e82019-03-15 22:02:34919 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16920 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
921 ),
922 True,
923 (
924 r'^sql/initialization\.(cc|h)$',
925 r'^third_party/sqlite/.*\.(c|cc|h)$',
926 ),
927 ),
Matt Menke7f520a82018-03-28 21:38:37928 (
929 'net::URLFetcher',
930 (
931 'net::URLFetcher should no longer be used in content embedders. ',
932 'Instead, use network::SimpleURLLoader instead, which supports ',
933 'an out-of-process network stack. ',
934 'net::URLFetcher may still be used in binaries that do not embed',
935 'content.',
936 ),
Matt Menke59716d02018-04-05 12:45:53937 False,
Matt Menke7f520a82018-03-28 21:38:37938 (
Egor Paskoce145c42018-09-28 19:31:04939 r'^ios[\\/].*\.(cc|h)$',
940 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37941 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04942 r'^net[\\/].*\.(cc|h)$',
943 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43944 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37945 ),
946 ),
jdoerried7d10ab2018-04-27 10:46:13947 (
Dave Tapuska98199b612019-07-10 13:30:44948 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47949 (
950 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
951 'base::RandomShuffle instead.'
952 ),
953 True,
954 (),
955 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24956 (
957 'ios/web/public/test/http_server',
958 (
959 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
960 ),
961 False,
962 (),
963 ),
Robert Liao764c9492019-01-24 18:46:28964 (
965 'GetAddressOf',
966 (
967 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46968 'implicated in a few leaks. Use operator& instead. See ',
969 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28970 ),
971 True,
972 (),
973 ),
Antonio Gomes07300d02019-03-13 20:59:57974 (
975 'DEFINE_TYPE_CASTS',
976 (
977 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
978 '//third_party/blink/renderer/platform/casting.h.'
979 ),
980 True,
981 (
982 r'^third_party/blink/renderer/.*\.(cc|h)$',
983 ),
984 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38985 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45986 r'/\bIsHTML.+Element\(\b',
987 (
988 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
989 ' helpers IsA<HTMLXXXXElement> from ',
990 '//third_party/blink/renderer/platform/casting.h.'
991 ),
992 False,
993 (
994 r'^third_party/blink/renderer/.*\.(cc|h)$',
995 ),
996 ),
997 (
998 r'/\bToHTML.+Element(|OrNull)\(\b',
999 (
1000 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1001 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1002 'and DynamicTo<HTMLXXXXElement> from ',
1003 '//third_party/blink/renderer/platform/casting.h.'
1004 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1005 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1006 ),
1007 False,
1008 (
1009 r'^third_party/blink/renderer/.*\.(cc|h)$',
1010 ),
1011 ),
1012 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371013 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381014 (
1015 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1016 ),
1017 True,
1018 (),
1019 ),
Ben Lewisa9514602019-04-29 17:53:051020 (
1021 'SHFileOperation',
1022 (
1023 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1024 'complex functions to achieve the same goals. Use IFileOperation for ',
1025 'any esoteric actions instead.'
1026 ),
1027 True,
1028 (),
1029 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181030 (
Cliff Smolinsky81951642019-04-30 21:39:511031 'StringFromGUID2',
1032 (
1033 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1034 'Use base::win::String16FromGUID instead.'
1035 ),
1036 True,
1037 (
1038 r'/base/win/win_util_unittest.cc'
1039 ),
1040 ),
1041 (
1042 'StringFromCLSID',
1043 (
1044 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1045 'Use base::win::String16FromGUID instead.'
1046 ),
1047 True,
1048 (
1049 r'/base/win/win_util_unittest.cc'
1050 ),
1051 ),
1052 (
Avi Drissman7382afa02019-04-29 23:27:131053 'kCFAllocatorNull',
1054 (
1055 'The use of kCFAllocatorNull with the NoCopy creation of ',
1056 'CoreFoundation types is prohibited.',
1057 ),
1058 True,
1059 (),
1060 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291061 (
1062 'mojo::ConvertTo',
1063 (
1064 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1065 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1066 'StringTraits if you would like to convert between custom types and',
1067 'the wire format of mojom types.'
1068 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221069 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291070 (
Wezf89dec092019-09-11 19:38:331071 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1072 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291073 r'^third_party/blink/.*\.(cc|h)$',
1074 r'^content/renderer/.*\.(cc|h)$',
1075 ),
1076 ),
Robert Liao1d78df52019-11-11 20:02:011077 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161078 'GetInterfaceProvider',
1079 (
1080 'InterfaceProvider is deprecated.',
1081 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1082 'or Platform::GetBrowserInterfaceBroker.'
1083 ),
1084 False,
1085 (),
1086 ),
1087 (
Robert Liao1d78df52019-11-11 20:02:011088 'CComPtr',
1089 (
1090 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1091 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1092 'details.'
1093 ),
1094 False,
1095 (),
1096 ),
[email protected]127f18ec2012-06-16 05:05:591097)
1098
Mario Sanchez Prada2472cab2019-09-18 10:58:311099# Format: Sequence of tuples containing:
1100# * String pattern or, if starting with a slash, a regular expression.
1101# * Sequence of strings to show when the pattern matches.
1102_DEPRECATED_MOJO_TYPES = (
1103 (
1104 r'/\bmojo::AssociatedBinding\b',
1105 (
1106 'mojo::AssociatedBinding<Interface> is deprecated.',
1107 'Use mojo::AssociatedReceiver<Interface> instead.',
1108 ),
1109 ),
1110 (
1111 r'/\bmojo::AssociatedBindingSet\b',
1112 (
1113 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1114 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1115 ),
1116 ),
1117 (
1118 r'/\bmojo::AssociatedInterfacePtr\b',
1119 (
1120 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1121 'Use mojo::AssociatedRemote<Interface> instead.',
1122 ),
1123 ),
1124 (
1125 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1126 (
1127 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1128 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1129 ),
1130 ),
1131 (
1132 r'/\bmojo::AssociatedInterfaceRequest\b',
1133 (
1134 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1135 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1136 ),
1137 ),
1138 (
1139 r'/\bmojo::Binding\b',
1140 (
1141 'mojo::Binding<Interface> is deprecated.',
1142 'Use mojo::Receiver<Interface> instead.',
1143 ),
1144 ),
1145 (
1146 r'/\bmojo::BindingSet\b',
1147 (
1148 'mojo::BindingSet<Interface> is deprecated.',
1149 'Use mojo::ReceiverSet<Interface> instead.',
1150 ),
1151 ),
1152 (
1153 r'/\bmojo::InterfacePtr\b',
1154 (
1155 'mojo::InterfacePtr<Interface> is deprecated.',
1156 'Use mojo::Remote<Interface> instead.',
1157 ),
1158 ),
1159 (
1160 r'/\bmojo::InterfacePtrInfo\b',
1161 (
1162 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1163 'Use mojo::PendingRemote<Interface> instead.',
1164 ),
1165 ),
1166 (
1167 r'/\bmojo::InterfaceRequest\b',
1168 (
1169 'mojo::InterfaceRequest<Interface> is deprecated.',
1170 'Use mojo::PendingReceiver<Interface> instead.',
1171 ),
1172 ),
1173 (
1174 r'/\bmojo::MakeRequest\b',
1175 (
1176 'mojo::MakeRequest is deprecated.',
1177 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1178 ),
1179 ),
1180 (
1181 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1182 (
1183 'mojo::MakeRequest is deprecated.',
1184 'Use mojo::AssociatedRemote::'
1185 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1186 ),
1187 ),
1188 (
1189 r'/\bmojo::MakeStrongBinding\b',
1190 (
1191 'mojo::MakeStrongBinding is deprecated.',
1192 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1193 'mojo::MakeSelfOwnedReceiver() instead.',
1194 ),
1195 ),
1196 (
1197 r'/\bmojo::MakeStrongAssociatedBinding\b',
1198 (
1199 'mojo::MakeStrongAssociatedBinding is deprecated.',
1200 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1201 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1202 ),
1203 ),
1204 (
1205 r'/\bmojo::StrongAssociatedBindingSet\b',
1206 (
1207 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1208 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1209 ),
1210 ),
1211 (
1212 r'/\bmojo::StrongBindingSet\b',
1213 (
1214 'mojo::StrongBindingSet<Interface> is deprecated.',
1215 'Use mojo::UniqueReceiverSet<Interface> instead.',
1216 ),
1217 ),
1218)
wnwenbdc444e2016-05-25 13:44:151219
mlamouria82272622014-09-16 18:45:041220_IPC_ENUM_TRAITS_DEPRECATED = (
1221 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501222 'See http://www.chromium.org/Home/chromium-security/education/'
1223 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041224
Stephen Martinis97a394142018-06-07 23:06:051225_LONG_PATH_ERROR = (
1226 'Some files included in this CL have file names that are too long (> 200'
1227 ' characters). If committed, these files will cause issues on Windows. See'
1228 ' https://crbug.com/612667 for more details.'
1229)
1230
Shenghua Zhangbfaa38b82017-11-16 21:58:021231_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041232 r".*[\\/]BuildHooksAndroidImpl\.java",
1233 r".*[\\/]LicenseContentProvider\.java",
1234 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281235 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021236]
[email protected]127f18ec2012-06-16 05:05:591237
Mohamed Heikald048240a2019-11-12 16:57:371238# List of image extensions that are used as resources in chromium.
1239_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1240
Sean Kau46e29bc2017-08-28 16:31:161241# These paths contain test data and other known invalid JSON files.
1242_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041243 r'test[\\/]data[\\/]',
1244 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1245 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041246 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431247 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161248]
1249
1250
[email protected]b00342e7f2013-03-26 16:21:541251_VALID_OS_MACROS = (
1252 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081253 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541254 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121255 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541256 'OS_BSD',
1257 'OS_CAT', # For testing.
1258 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041259 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541260 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371261 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541262 'OS_IOS',
1263 'OS_LINUX',
1264 'OS_MACOSX',
1265 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211266 'OS_NACL_NONSFI',
1267 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121268 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541269 'OS_OPENBSD',
1270 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371271 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541272 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541273 'OS_WIN',
1274)
1275
1276
agrievef32bcc72016-04-04 14:57:401277_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391278 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361279 'base/android/jni_generator/jni_generator.pydeps',
1280 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221281 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361282 'build/android/gyp/aar.pydeps',
1283 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271284 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361285 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381286 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361287 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111288 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361289 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361290 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361291 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111292 'build/android/gyp/create_app_bundle_apks.pydeps',
1293 'build/android/gyp/create_app_bundle.pydeps',
1294 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361295 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221296 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361297 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591298 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361299 'build/android/gyp/dex.pydeps',
1300 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361301 'build/android/gyp/filter_zip.pydeps',
1302 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361303 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581305 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361306 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261307 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/jinja_template.pydeps',
1309 'build/android/gyp/lint.pydeps',
1310 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361311 'build/android/gyp/merge_manifest.pydeps',
1312 'build/android/gyp/prepare_resources.pydeps',
1313 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241314 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361315 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461316 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561317 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361318 'build/android/incremental_install/generate_android_manifest.pydeps',
1319 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221320 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401321 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041322 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361323 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411324 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051325 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191326 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431327 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021328 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401329]
1330
wnwenbdc444e2016-05-25 13:44:151331
agrievef32bcc72016-04-04 14:57:401332_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421333 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131334 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421335 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1336 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131337 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191338 ('third_party/blink/renderer/bindings/scripts/'
1339 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061340 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221341 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401342]
1343
wnwenbdc444e2016-05-25 13:44:151344
agrievef32bcc72016-04-04 14:57:401345_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1346
1347
Eric Boren6fd2b932018-01-25 15:05:081348# Bypass the AUTHORS check for these accounts.
1349_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591350 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451351 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591352 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521353 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1354 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041355 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271356 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041357 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301358 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081359
1360
Daniel Bratell65b033262019-04-23 08:17:061361def _IsCPlusPlusFile(input_api, file_path):
1362 """Returns True if this file contains C++-like code (and not Python,
1363 Go, Java, MarkDown, ...)"""
1364
1365 ext = input_api.os_path.splitext(file_path)[1]
1366 # This list is compatible with CppChecker.IsCppFile but we should
1367 # consider adding ".c" to it. If we do that we can use this function
1368 # at more places in the code.
1369 return ext in (
1370 '.h',
1371 '.cc',
1372 '.cpp',
1373 '.m',
1374 '.mm',
1375 )
1376
1377def _IsCPlusPlusHeaderFile(input_api, file_path):
1378 return input_api.os_path.splitext(file_path)[1] == ".h"
1379
1380
1381def _IsJavaFile(input_api, file_path):
1382 return input_api.os_path.splitext(file_path)[1] == ".java"
1383
1384
1385def _IsProtoFile(input_api, file_path):
1386 return input_api.os_path.splitext(file_path)[1] == ".proto"
1387
[email protected]55459852011-08-10 15:17:191388def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1389 """Attempts to prevent use of functions intended only for testing in
1390 non-testing code. For now this is just a best-effort implementation
1391 that ignores header files and may have some false positives. A
1392 better implementation would probably need a proper C++ parser.
1393 """
1394 # We only scan .cc files and the like, as the declaration of
1395 # for-testing functions in header files are hard to distinguish from
1396 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491397 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191398
jochenc0d4808c2015-07-27 09:25:421399 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191400 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091401 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191402 exclusion_pattern = input_api.re.compile(
1403 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1404 base_function_pattern, base_function_pattern))
1405
1406 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441407 black_list = (_EXCLUDED_PATHS +
1408 _TEST_CODE_EXCLUDED_PATHS +
1409 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191410 return input_api.FilterSourceFile(
1411 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491412 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191413 black_list=black_list)
1414
1415 problems = []
1416 for f in input_api.AffectedSourceFiles(FilterFile):
1417 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241418 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031419 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461420 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031421 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191422 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031423 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191424
1425 if problems:
[email protected]f7051d52013-04-02 18:31:421426 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031427 else:
1428 return []
[email protected]55459852011-08-10 15:17:191429
1430
Vaclav Brozek7dbc28c2018-03-27 08:35:231431def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1432 """This is a simplified version of
1433 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1434 """
1435 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1436 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1437 name_pattern = r'ForTest(s|ing)?'
1438 # Describes an occurrence of "ForTest*" inside a // comment.
1439 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1440 # Catch calls.
1441 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1442 # Ignore definitions. (Comments are ignored separately.)
1443 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1444
1445 problems = []
1446 sources = lambda x: input_api.FilterSourceFile(
1447 x,
1448 black_list=(('(?i).*test', r'.*\/junit\/')
1449 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491450 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231451 )
1452 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1453 local_path = f.LocalPath()
1454 is_inside_javadoc = False
1455 for line_number, line in f.ChangedContents():
1456 if is_inside_javadoc and javadoc_end_re.search(line):
1457 is_inside_javadoc = False
1458 if not is_inside_javadoc and javadoc_start_re.search(line):
1459 is_inside_javadoc = True
1460 if is_inside_javadoc:
1461 continue
1462 if (inclusion_re.search(line) and
1463 not comment_re.search(line) and
1464 not exclusion_re.search(line)):
1465 problems.append(
1466 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1467
1468 if problems:
1469 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1470 else:
1471 return []
1472
1473
[email protected]10689ca2011-09-02 02:31:541474def _CheckNoIOStreamInHeaders(input_api, output_api):
1475 """Checks to make sure no .h files include <iostream>."""
1476 files = []
1477 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1478 input_api.re.MULTILINE)
1479 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1480 if not f.LocalPath().endswith('.h'):
1481 continue
1482 contents = input_api.ReadFile(f)
1483 if pattern.search(contents):
1484 files.append(f)
1485
1486 if len(files):
yolandyandaabc6d2016-04-18 18:29:391487 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061488 'Do not #include <iostream> in header files, since it inserts static '
1489 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541490 '#include <ostream>. See http://crbug.com/94794',
1491 files) ]
1492 return []
1493
Danil Chapovalov3518f362018-08-11 16:13:431494def _CheckNoStrCatRedefines(input_api, output_api):
1495 """Checks no windows headers with StrCat redefined are included directly."""
1496 files = []
1497 pattern_deny = input_api.re.compile(
1498 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1499 input_api.re.MULTILINE)
1500 pattern_allow = input_api.re.compile(
1501 r'^#include\s"base/win/windows_defines.inc"',
1502 input_api.re.MULTILINE)
1503 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1504 contents = input_api.ReadFile(f)
1505 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1506 files.append(f.LocalPath())
1507
1508 if len(files):
1509 return [output_api.PresubmitError(
1510 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1511 'directly since they pollute code with StrCat macro. Instead, '
1512 'include matching header from base/win. See http://crbug.com/856536',
1513 files) ]
1514 return []
1515
[email protected]10689ca2011-09-02 02:31:541516
[email protected]72df4e782012-06-21 16:28:181517def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521518 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181519 problems = []
1520 for f in input_api.AffectedFiles():
1521 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1522 continue
1523
1524 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041525 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181526 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1527
1528 if not problems:
1529 return []
1530 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1531 '\n'.join(problems))]
1532
Dominic Battre033531052018-09-24 15:45:341533def _CheckNoDISABLETypoInTests(input_api, output_api):
1534 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1535
1536 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1537 instead of DISABLED_. To filter false positives, reports are only generated
1538 if a corresponding MAYBE_ line exists.
1539 """
1540 problems = []
1541
1542 # The following two patterns are looked for in tandem - is a test labeled
1543 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1544 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1545 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1546
1547 # This is for the case that a test is disabled on all platforms.
1548 full_disable_pattern = input_api.re.compile(
1549 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1550 input_api.re.MULTILINE)
1551
Katie Df13948e2018-09-25 07:33:441552 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341553 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1554 continue
1555
1556 # Search for MABYE_, DISABLE_ pairs.
1557 disable_lines = {} # Maps of test name to line number.
1558 maybe_lines = {}
1559 for line_num, line in f.ChangedContents():
1560 disable_match = disable_pattern.search(line)
1561 if disable_match:
1562 disable_lines[disable_match.group(1)] = line_num
1563 maybe_match = maybe_pattern.search(line)
1564 if maybe_match:
1565 maybe_lines[maybe_match.group(1)] = line_num
1566
1567 # Search for DISABLE_ occurrences within a TEST() macro.
1568 disable_tests = set(disable_lines.keys())
1569 maybe_tests = set(maybe_lines.keys())
1570 for test in disable_tests.intersection(maybe_tests):
1571 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1572
1573 contents = input_api.ReadFile(f)
1574 full_disable_match = full_disable_pattern.search(contents)
1575 if full_disable_match:
1576 problems.append(' %s' % f.LocalPath())
1577
1578 if not problems:
1579 return []
1580 return [
1581 output_api.PresubmitPromptWarning(
1582 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1583 '\n'.join(problems))
1584 ]
1585
[email protected]72df4e782012-06-21 16:28:181586
danakj61c1aa22015-10-26 19:55:521587def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571588 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521589 errors = []
1590 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1591 input_api.re.MULTILINE)
1592 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1593 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1594 continue
1595 for lnum, line in f.ChangedContents():
1596 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171597 errors.append(output_api.PresubmitError(
1598 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571599 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171600 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521601 return errors
1602
1603
Makoto Shimazu3ad422cd2019-05-08 02:35:141604def _FindHistogramNameInChunk(histogram_name, chunk):
1605 """Tries to find a histogram name or prefix in a line.
1606
1607 Returns the existence of the histogram name, or None if it needs more chunk
1608 to determine."""
mcasasb7440c282015-02-04 14:52:191609 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1610 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141611 if '<affected-histogram' in chunk:
1612 # If the tag is not completed, needs more chunk to get the name.
1613 if not '>' in chunk:
1614 return None
1615 if not 'name="' in chunk:
1616 return False
1617 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1618 # expect the only attribute is the name.
1619 histogram_prefix = chunk.split('"')[1]
1620 return histogram_prefix in histogram_name
1621 # Typically the whole histogram name should in the line.
1622 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191623
1624
1625def _CheckUmaHistogramChanges(input_api, output_api):
1626 """Check that UMA histogram names in touched lines can still be found in other
1627 lines of the patch or in histograms.xml. Note that this check would not catch
1628 the reverse: changes in histograms.xml not matched in the code itself."""
1629 touched_histograms = []
1630 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471631 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1632 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1633 name_pattern = r'"(.*?)"'
1634 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1635 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1636 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1637 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1638 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171639 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191640 for f in input_api.AffectedFiles():
1641 # If histograms.xml itself is modified, keep the modified lines for later.
1642 if f.LocalPath().endswith(('histograms.xml')):
1643 histograms_xml_modifications = f.ChangedContents()
1644 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471645 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1646 single_line_re = single_line_c_re
1647 split_line_prefix_re = split_line_c_prefix_re
1648 elif f.LocalPath().endswith(('java')):
1649 single_line_re = single_line_java_re
1650 split_line_prefix_re = split_line_java_prefix_re
1651 else:
mcasasb7440c282015-02-04 14:52:191652 continue
1653 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171654 if last_line_matched_prefix:
1655 suffix_found = split_line_suffix_re.search(line)
1656 if suffix_found :
1657 touched_histograms.append([suffix_found.group(1), f, line_num])
1658 last_line_matched_prefix = False
1659 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061660 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191661 if found:
1662 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171663 continue
1664 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191665
1666 # Search for the touched histogram names in the local modifications to
1667 # histograms.xml, and, if not found, on the base histograms.xml file.
1668 unmatched_histograms = []
1669 for histogram_info in touched_histograms:
1670 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141671 chunk = ''
mcasasb7440c282015-02-04 14:52:191672 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141673 chunk += line
1674 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1675 if histogram_name_found is None:
1676 continue
1677 chunk = ''
mcasasb7440c282015-02-04 14:52:191678 if histogram_name_found:
1679 break
1680 if not histogram_name_found:
1681 unmatched_histograms.append(histogram_info)
1682
eromanb90c82e7e32015-04-01 15:13:491683 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191684 problems = []
1685 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491686 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191687 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451688 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191689 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141690 chunk = ''
mcasasb7440c282015-02-04 14:52:191691 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141692 chunk += line
1693 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1694 chunk)
1695 if histogram_name_found is None:
1696 continue
1697 chunk = ''
mcasasb7440c282015-02-04 14:52:191698 if histogram_name_found:
1699 break
1700 if not histogram_name_found:
1701 problems.append(' [%s:%d] %s' %
1702 (f.LocalPath(), line_num, histogram_name))
1703
1704 if not problems:
1705 return []
1706 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1707 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491708 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191709
wnwenbdc444e2016-05-25 13:44:151710
yolandyandaabc6d2016-04-18 18:29:391711def _CheckFlakyTestUsage(input_api, output_api):
1712 """Check that FlakyTest annotation is our own instead of the android one"""
1713 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1714 files = []
1715 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1716 if f.LocalPath().endswith('Test.java'):
1717 if pattern.search(input_api.ReadFile(f)):
1718 files.append(f)
1719 if len(files):
1720 return [output_api.PresubmitError(
1721 'Use org.chromium.base.test.util.FlakyTest instead of '
1722 'android.test.FlakyTest',
1723 files)]
1724 return []
mcasasb7440c282015-02-04 14:52:191725
wnwenbdc444e2016-05-25 13:44:151726
[email protected]8ea5d4b2011-09-13 21:49:221727def _CheckNoNewWStrings(input_api, output_api):
1728 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271729 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221730 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201731 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571732 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341733 '/win/' in f.LocalPath() or
1734 'chrome_elf' in f.LocalPath() or
1735 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201736 continue
[email protected]8ea5d4b2011-09-13 21:49:221737
[email protected]a11dbe9b2012-08-07 01:32:581738 allowWString = False
[email protected]b5c24292011-11-28 14:38:201739 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581740 if 'presubmit: allow wstring' in line:
1741 allowWString = True
1742 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271743 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581744 allowWString = False
1745 else:
1746 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221747
[email protected]55463aa62011-10-12 00:48:271748 if not problems:
1749 return []
1750 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581751 ' If you are calling a cross-platform API that accepts a wstring, '
1752 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271753 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221754
1755
[email protected]2a8ac9c2011-10-19 17:20:441756def _CheckNoDEPSGIT(input_api, output_api):
1757 """Make sure .DEPS.git is never modified manually."""
1758 if any(f.LocalPath().endswith('.DEPS.git') for f in
1759 input_api.AffectedFiles()):
1760 return [output_api.PresubmitError(
1761 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1762 'automated system based on what\'s in DEPS and your changes will be\n'
1763 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501764 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1765 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441766 'for more information')]
1767 return []
1768
1769
tandriief664692014-09-23 14:51:471770def _CheckValidHostsInDEPS(input_api, output_api):
1771 """Checks that DEPS file deps are from allowed_hosts."""
1772 # Run only if DEPS file has been modified to annoy fewer bystanders.
1773 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1774 return []
1775 # Outsource work to gclient verify
1776 try:
John Budorickf20c0042019-04-25 23:23:401777 gclient_path = input_api.os_path.join(
1778 input_api.PresubmitLocalPath(),
1779 'third_party', 'depot_tools', 'gclient.py')
1780 input_api.subprocess.check_output(
1781 [input_api.python_executable, gclient_path, 'verify'],
1782 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471783 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201784 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471785 return [output_api.PresubmitError(
1786 'DEPS file must have only git dependencies.',
1787 long_text=error.output)]
1788
1789
Mario Sanchez Prada2472cab2019-09-18 10:58:311790def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1791 type_name, message):
1792 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1793
1794 Returns an string composed of the name of the file, the line number where the
1795 match has been found and the additional text passed as |message| in case the
1796 target type name matches the text inside the line passed as parameter.
1797 """
1798 matched = False
1799 if type_name[0:1] == '/':
1800 regex = type_name[1:]
1801 if input_api.re.search(regex, line):
1802 matched = True
1803 elif type_name in line:
1804 matched = True
1805
1806 result = []
1807 if matched:
1808 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1809 for message_line in message:
1810 result.append(' %s' % message_line)
1811
1812 return result
1813
1814
[email protected]127f18ec2012-06-16 05:05:591815def _CheckNoBannedFunctions(input_api, output_api):
1816 """Make sure that banned functions are not used."""
1817 warnings = []
1818 errors = []
1819
wnwenbdc444e2016-05-25 13:44:151820 def IsBlacklisted(affected_file, blacklist):
1821 local_path = affected_file.LocalPath()
1822 for item in blacklist:
1823 if input_api.re.match(item, local_path):
1824 return True
1825 return False
1826
Peter K. Lee6c03ccff2019-07-15 14:40:051827 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541828 local_path = affected_file.LocalPath()
1829 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1830 return False
1831 basename = input_api.os_path.basename(local_path)
1832 if 'ios' in basename.split('_'):
1833 return True
1834 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1835 if sep and 'ios' in local_path.split(sep):
1836 return True
1837 return False
1838
wnwenbdc444e2016-05-25 13:44:151839 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311840 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1841 func_name, message)
1842 if problems:
wnwenbdc444e2016-05-25 13:44:151843 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311844 errors.extend(problems)
1845 else:
1846 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151847
Eric Stevensona9a980972017-09-23 00:04:411848 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1849 for f in input_api.AffectedFiles(file_filter=file_filter):
1850 for line_num, line in f.ChangedContents():
1851 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1852 CheckForMatch(f, line_num, line, func_name, message, error)
1853
[email protected]127f18ec2012-06-16 05:05:591854 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1855 for f in input_api.AffectedFiles(file_filter=file_filter):
1856 for line_num, line in f.ChangedContents():
1857 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151858 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591859
Peter K. Lee6c03ccff2019-07-15 14:40:051860 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541861 for line_num, line in f.ChangedContents():
1862 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1863 CheckForMatch(f, line_num, line, func_name, message, error)
1864
Peter K. Lee6c03ccff2019-07-15 14:40:051865 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1866 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1867 for line_num, line in f.ChangedContents():
1868 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1869 CheckForMatch(f, line_num, line, func_name, message, error)
1870
[email protected]127f18ec2012-06-16 05:05:591871 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1872 for f in input_api.AffectedFiles(file_filter=file_filter):
1873 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491874 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491875 if IsBlacklisted(f, excluded_paths):
1876 continue
wnwenbdc444e2016-05-25 13:44:151877 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591878
1879 result = []
1880 if (warnings):
1881 result.append(output_api.PresubmitPromptWarning(
1882 'Banned functions were used.\n' + '\n'.join(warnings)))
1883 if (errors):
1884 result.append(output_api.PresubmitError(
1885 'Banned functions were used.\n' + '\n'.join(errors)))
1886 return result
1887
1888
Mario Sanchez Prada2472cab2019-09-18 10:58:311889def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1890 """Make sure that old Mojo types are not used."""
1891 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571892 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311893
Mario Sanchez Pradaaab91382019-12-19 08:57:091894 # For any path that is not an "ok" or an "error" path, a warning will be
1895 # raised if deprecated mojo types are found.
1896 ok_paths = ['components/arc']
1897 error_paths = ['third_party/blink', 'content']
1898
Mario Sanchez Prada2472cab2019-09-18 10:58:311899 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1900 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571901 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091902 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311903 continue
1904
1905 for line_num, line in f.ChangedContents():
1906 for func_name, message in _DEPRECATED_MOJO_TYPES:
1907 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1908 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571909
Mario Sanchez Prada2472cab2019-09-18 10:58:311910 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091911 # Raise errors inside |error_paths| and warnings everywhere else.
1912 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571913 errors.extend(problems)
1914 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311915 warnings.extend(problems)
1916
1917 result = []
1918 if (warnings):
1919 result.append(output_api.PresubmitPromptWarning(
1920 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571921 if (errors):
1922 result.append(output_api.PresubmitError(
1923 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311924 return result
1925
1926
[email protected]6c063c62012-07-11 19:11:061927def _CheckNoPragmaOnce(input_api, output_api):
1928 """Make sure that banned functions are not used."""
1929 files = []
1930 pattern = input_api.re.compile(r'^#pragma\s+once',
1931 input_api.re.MULTILINE)
1932 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1933 if not f.LocalPath().endswith('.h'):
1934 continue
1935 contents = input_api.ReadFile(f)
1936 if pattern.search(contents):
1937 files.append(f)
1938
1939 if files:
1940 return [output_api.PresubmitError(
1941 'Do not use #pragma once in header files.\n'
1942 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1943 files)]
1944 return []
1945
[email protected]127f18ec2012-06-16 05:05:591946
[email protected]e7479052012-09-19 00:26:121947def _CheckNoTrinaryTrueFalse(input_api, output_api):
1948 """Checks to make sure we don't introduce use of foo ? true : false."""
1949 problems = []
1950 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1951 for f in input_api.AffectedFiles():
1952 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1953 continue
1954
1955 for line_num, line in f.ChangedContents():
1956 if pattern.match(line):
1957 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1958
1959 if not problems:
1960 return []
1961 return [output_api.PresubmitPromptWarning(
1962 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1963 '\n'.join(problems))]
1964
1965
[email protected]55f9f382012-07-31 11:02:181966def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281967 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181968 change. Breaking - rules is an error, breaking ! rules is a
1969 warning.
1970 """
mohan.reddyf21db962014-10-16 12:26:471971 import sys
[email protected]55f9f382012-07-31 11:02:181972 # We need to wait until we have an input_api object and use this
1973 # roundabout construct to import checkdeps because this file is
1974 # eval-ed and thus doesn't have __file__.
1975 original_sys_path = sys.path
1976 try:
1977 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471978 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181979 import checkdeps
[email protected]55f9f382012-07-31 11:02:181980 from rules import Rule
1981 finally:
1982 # Restore sys.path to what it was before.
1983 sys.path = original_sys_path
1984
1985 added_includes = []
rhalavati08acd232017-04-03 07:23:281986 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241987 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181988 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:061989 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501990 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081991 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061992 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501993 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081994 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:061995 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:501996 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:081997 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:181998
[email protected]26385172013-05-09 23:11:351999 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182000
2001 error_descriptions = []
2002 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282003 error_subjects = set()
2004 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182005 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2006 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082007 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182008 description_with_path = '%s\n %s' % (path, rule_description)
2009 if rule_type == Rule.DISALLOW:
2010 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282011 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182012 else:
2013 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282014 warning_subjects.add("#includes")
2015
2016 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2017 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082018 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282019 description_with_path = '%s\n %s' % (path, rule_description)
2020 if rule_type == Rule.DISALLOW:
2021 error_descriptions.append(description_with_path)
2022 error_subjects.add("imports")
2023 else:
2024 warning_descriptions.append(description_with_path)
2025 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182026
Jinsuk Kim5a092672017-10-24 22:42:242027 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022028 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082029 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242030 description_with_path = '%s\n %s' % (path, rule_description)
2031 if rule_type == Rule.DISALLOW:
2032 error_descriptions.append(description_with_path)
2033 error_subjects.add("imports")
2034 else:
2035 warning_descriptions.append(description_with_path)
2036 warning_subjects.add("imports")
2037
[email protected]55f9f382012-07-31 11:02:182038 results = []
2039 if error_descriptions:
2040 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282041 'You added one or more %s that violate checkdeps rules.'
2042 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182043 error_descriptions))
2044 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422045 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282046 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182047 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282048 '%s? See relevant DEPS file(s) for details and contacts.' %
2049 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182050 warning_descriptions))
2051 return results
2052
2053
[email protected]fbcafe5a2012-08-08 15:31:222054def _CheckFilePermissions(input_api, output_api):
2055 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152056 if input_api.platform == 'win32':
2057 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292058 checkperms_tool = input_api.os_path.join(
2059 input_api.PresubmitLocalPath(),
2060 'tools', 'checkperms', 'checkperms.py')
2061 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472062 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392063 with input_api.CreateTemporaryFile() as file_list:
2064 for f in input_api.AffectedFiles():
2065 # checkperms.py file/directory arguments must be relative to the
2066 # repository.
2067 file_list.write(f.LocalPath() + '\n')
2068 file_list.close()
2069 args += ['--file-list', file_list.name]
2070 try:
2071 input_api.subprocess.check_output(args)
2072 return []
2073 except input_api.subprocess.CalledProcessError as error:
2074 return [output_api.PresubmitError(
2075 'checkperms.py failed:',
2076 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222077
2078
robertocn832f5992017-01-04 19:01:302079def _CheckTeamTags(input_api, output_api):
2080 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2081 checkteamtags_tool = input_api.os_path.join(
2082 input_api.PresubmitLocalPath(),
2083 'tools', 'checkteamtags', 'checkteamtags.py')
2084 args = [input_api.python_executable, checkteamtags_tool,
2085 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222086 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302087 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2088 'OWNERS']
2089 try:
2090 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052091 warnings = input_api.subprocess.check_output(args + files).splitlines()
2092 if warnings:
2093 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302094 return []
2095 except input_api.subprocess.CalledProcessError as error:
2096 return [output_api.PresubmitError(
2097 'checkteamtags.py failed:',
2098 long_text=error.output)]
2099
2100
[email protected]c8278b32012-10-30 20:35:492101def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2102 """Makes sure we don't include ui/aura/window_property.h
2103 in header files.
2104 """
2105 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2106 errors = []
2107 for f in input_api.AffectedFiles():
2108 if not f.LocalPath().endswith('.h'):
2109 continue
2110 for line_num, line in f.ChangedContents():
2111 if pattern.match(line):
2112 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2113
2114 results = []
2115 if errors:
2116 results.append(output_api.PresubmitError(
2117 'Header files should not include ui/aura/window_property.h', errors))
2118 return results
2119
2120
[email protected]70ca77752012-11-20 03:45:032121def _CheckForVersionControlConflictsInFile(input_api, f):
2122 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2123 errors = []
2124 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162125 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232126 # First-level headers in markdown look a lot like version control
2127 # conflict markers. http://daringfireball.net/projects/markdown/basics
2128 continue
[email protected]70ca77752012-11-20 03:45:032129 if pattern.match(line):
2130 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2131 return errors
2132
2133
2134def _CheckForVersionControlConflicts(input_api, output_api):
2135 """Usually this is not intentional and will cause a compile failure."""
2136 errors = []
2137 for f in input_api.AffectedFiles():
2138 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2139
2140 results = []
2141 if errors:
2142 results.append(output_api.PresubmitError(
2143 'Version control conflict markers found, please resolve.', errors))
2144 return results
2145
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202146
estadee17314a02017-01-12 16:22:162147def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2148 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2149 errors = []
2150 for f in input_api.AffectedFiles():
2151 for line_num, line in f.ChangedContents():
2152 if pattern.search(line):
2153 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2154
2155 results = []
2156 if errors:
2157 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502158 'Found Google support URL addressed by answer number. Please replace '
2159 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162160 return results
2161
[email protected]70ca77752012-11-20 03:45:032162
[email protected]06e6d0ff2012-12-11 01:36:442163def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2164 def FilterFile(affected_file):
2165 """Filter function for use with input_api.AffectedSourceFiles,
2166 below. This filters out everything except non-test files from
2167 top-level directories that generally speaking should not hard-code
2168 service URLs (e.g. src/android_webview/, src/content/ and others).
2169 """
2170 return input_api.FilterSourceFile(
2171 affected_file,
Egor Paskoce145c42018-09-28 19:31:042172 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442173 black_list=(_EXCLUDED_PATHS +
2174 _TEST_CODE_EXCLUDED_PATHS +
2175 input_api.DEFAULT_BLACK_LIST))
2176
reillyi38965732015-11-16 18:27:332177 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2178 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462179 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2180 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442181 problems = [] # items are (filename, line_number, line)
2182 for f in input_api.AffectedSourceFiles(FilterFile):
2183 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462184 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442185 problems.append((f.LocalPath(), line_num, line))
2186
2187 if problems:
[email protected]f7051d52013-04-02 18:31:422188 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442189 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582190 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442191 [' %s:%d: %s' % (
2192 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032193 else:
2194 return []
[email protected]06e6d0ff2012-12-11 01:36:442195
2196
James Cook6b6597c2019-11-06 22:05:292197def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2198 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2199 def FileFilter(affected_file):
2200 """Includes directories known to be Chrome OS only."""
2201 return input_api.FilterSourceFile(
2202 affected_file,
2203 white_list=('^ash/',
2204 '^chromeos/', # Top-level src/chromeos.
2205 '/chromeos/', # Any path component.
2206 '^components/arc',
2207 '^components/exo'),
2208 black_list=(input_api.DEFAULT_BLACK_LIST))
2209
2210 prefs = []
2211 priority_prefs = []
2212 for f in input_api.AffectedFiles(file_filter=FileFilter):
2213 for line_num, line in f.ChangedContents():
2214 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2215 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2216 prefs.append(' %s' % line)
2217 if input_api.re.search(
2218 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2219 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2220 priority_prefs.append(' %s' % line)
2221
2222 results = []
2223 if (prefs):
2224 results.append(output_api.PresubmitPromptWarning(
2225 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2226 'by browser sync settings. If these prefs should be controlled by OS '
2227 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2228 if (priority_prefs):
2229 results.append(output_api.PresubmitPromptWarning(
2230 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2231 'controlled by browser sync settings. If these prefs should be '
2232 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2233 'instead.\n' + '\n'.join(prefs)))
2234 return results
2235
2236
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492237# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272238def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2239 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312240 The native_client_sdk directory is excluded because it has auto-generated PNG
2241 files for documentation.
[email protected]d2530012013-01-25 16:39:272242 """
[email protected]d2530012013-01-25 16:39:272243 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492244 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042245 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312246 file_filter = lambda f: input_api.FilterSourceFile(
2247 f, white_list=white_list, black_list=black_list)
2248 for f in input_api.AffectedFiles(include_deletes=False,
2249 file_filter=file_filter):
2250 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272251
2252 results = []
2253 if errors:
2254 results.append(output_api.PresubmitError(
2255 'The name of PNG files should not have abbreviations. \n'
2256 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2257 'Contact [email protected] if you have questions.', errors))
2258 return results
2259
2260
Daniel Cheng4dcdb6b2017-04-13 08:30:172261def _ExtractAddRulesFromParsedDeps(parsed_deps):
2262 """Extract the rules that add dependencies from a parsed DEPS file.
2263
2264 Args:
2265 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2266 add_rules = set()
2267 add_rules.update([
2268 rule[1:] for rule in parsed_deps.get('include_rules', [])
2269 if rule.startswith('+') or rule.startswith('!')
2270 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502271 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172272 {}).iteritems():
2273 add_rules.update([
2274 rule[1:] for rule in rules
2275 if rule.startswith('+') or rule.startswith('!')
2276 ])
2277 return add_rules
2278
2279
2280def _ParseDeps(contents):
2281 """Simple helper for parsing DEPS files."""
2282 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172283 class _VarImpl:
2284
2285 def __init__(self, local_scope):
2286 self._local_scope = local_scope
2287
2288 def Lookup(self, var_name):
2289 """Implements the Var syntax."""
2290 try:
2291 return self._local_scope['vars'][var_name]
2292 except KeyError:
2293 raise Exception('Var is not defined: %s' % var_name)
2294
2295 local_scope = {}
2296 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172297 'Var': _VarImpl(local_scope).Lookup,
2298 }
2299 exec contents in global_scope, local_scope
2300 return local_scope
2301
2302
2303def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082304 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412305 a set of DEPS entries that we should look up.
2306
2307 For a directory (rather than a specific filename) we fake a path to
2308 a specific filename by adding /DEPS. This is chosen as a file that
2309 will seldom or never be subject to per-file include_rules.
2310 """
[email protected]2b438d62013-11-14 17:54:142311 # We ignore deps entries on auto-generated directories.
2312 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082313
Daniel Cheng4dcdb6b2017-04-13 08:30:172314 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2315 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2316
2317 added_deps = new_deps.difference(old_deps)
2318
[email protected]2b438d62013-11-14 17:54:142319 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172320 for added_dep in added_deps:
2321 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2322 continue
2323 # Assume that a rule that ends in .h is a rule for a specific file.
2324 if added_dep.endswith('.h'):
2325 results.add(added_dep)
2326 else:
2327 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082328 return results
2329
2330
[email protected]e871964c2013-05-13 14:14:552331def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2332 """When a dependency prefixed with + is added to a DEPS file, we
2333 want to make sure that the change is reviewed by an OWNER of the
2334 target file or directory, to avoid layering violations from being
2335 introduced. This check verifies that this happens.
2336 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172337 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242338
2339 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492340 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242341 for f in input_api.AffectedFiles(include_deletes=False,
2342 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552343 filename = input_api.os_path.basename(f.LocalPath())
2344 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172345 virtual_depended_on_files.update(_CalculateAddedDeps(
2346 input_api.os_path,
2347 '\n'.join(f.OldContents()),
2348 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552349
[email protected]e871964c2013-05-13 14:14:552350 if not virtual_depended_on_files:
2351 return []
2352
2353 if input_api.is_committing:
2354 if input_api.tbr:
2355 return [output_api.PresubmitNotifyResult(
2356 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272357 if input_api.dry_run:
2358 return [output_api.PresubmitNotifyResult(
2359 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552360 if not input_api.change.issue:
2361 return [output_api.PresubmitError(
2362 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402363 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552364 output = output_api.PresubmitError
2365 else:
2366 output = output_api.PresubmitNotifyResult
2367
2368 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502369 owner_email, reviewers = (
2370 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2371 input_api,
2372 owners_db.email_regexp,
2373 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552374
2375 owner_email = owner_email or input_api.change.author_email
2376
[email protected]de4f7d22013-05-23 14:27:462377 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512378 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462379 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552380 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2381 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412382
2383 # We strip the /DEPS part that was added by
2384 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2385 # directory.
2386 def StripDeps(path):
2387 start_deps = path.rfind('/DEPS')
2388 if start_deps != -1:
2389 return path[:start_deps]
2390 else:
2391 return path
2392 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552393 for path in missing_files]
2394
2395 if unapproved_dependencies:
2396 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152397 output('You need LGTM from owners of depends-on paths in DEPS that were '
2398 'modified in this CL:\n %s' %
2399 '\n '.join(sorted(unapproved_dependencies)))]
2400 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2401 output_list.append(output(
2402 'Suggested missing target path OWNERS:\n %s' %
2403 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552404 return output_list
2405
2406 return []
2407
2408
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492409# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402410def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492411 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402412 black_list = (_EXCLUDED_PATHS +
2413 _TEST_CODE_EXCLUDED_PATHS +
2414 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042415 (r"^base[\\/]logging\.h$",
2416 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222417 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042418 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2419 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2420 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122421 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182422 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152423 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032424 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152425 r"^chrome[\\/]chrome_cleaner[\\/].*",
2426 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2427 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042428 r"^chromecast[\\/]",
2429 r"^cloud_print[\\/]",
2430 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482431 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042432 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312433 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042434 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462435 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042436 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462437 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042438 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252439 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042440 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2441 r"^courgette[\\/]courgette_tool\.cc$",
2442 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272443 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002444 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332445 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042446 r"^ipc[\\/]ipc_logging\.cc$",
2447 r"^native_client_sdk[\\/]",
2448 r"^remoting[\\/]base[\\/]logging\.h$",
2449 r"^remoting[\\/]host[\\/].*",
2450 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062451 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332452 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042453 r"^tools[\\/]",
2454 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2455 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332456 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402457 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492458 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402459
thomasanderson625d3932017-03-29 07:16:582460 log_info = set([])
2461 printf = set([])
[email protected]85218562013-11-22 07:41:402462
2463 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582464 for _, line in f.ChangedContents():
2465 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2466 log_info.add(f.LocalPath())
2467 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2468 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372469
thomasanderson625d3932017-03-29 07:16:582470 if input_api.re.search(r"\bprintf\(", line):
2471 printf.add(f.LocalPath())
2472 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2473 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402474
2475 if log_info:
2476 return [output_api.PresubmitError(
2477 'These files spam the console log with LOG(INFO):',
2478 items=log_info)]
2479 if printf:
2480 return [output_api.PresubmitError(
2481 'These files spam the console log with printf/fprintf:',
2482 items=printf)]
2483 return []
2484
2485
[email protected]49aa76a2013-12-04 06:59:162486def _CheckForAnonymousVariables(input_api, output_api):
2487 """These types are all expected to hold locks while in scope and
2488 so should never be anonymous (which causes them to be immediately
2489 destroyed)."""
2490 they_who_must_be_named = [
2491 'base::AutoLock',
2492 'base::AutoReset',
2493 'base::AutoUnlock',
2494 'SkAutoAlphaRestore',
2495 'SkAutoBitmapShaderInstall',
2496 'SkAutoBlitterChoose',
2497 'SkAutoBounderCommit',
2498 'SkAutoCallProc',
2499 'SkAutoCanvasRestore',
2500 'SkAutoCommentBlock',
2501 'SkAutoDescriptor',
2502 'SkAutoDisableDirectionCheck',
2503 'SkAutoDisableOvalCheck',
2504 'SkAutoFree',
2505 'SkAutoGlyphCache',
2506 'SkAutoHDC',
2507 'SkAutoLockColors',
2508 'SkAutoLockPixels',
2509 'SkAutoMalloc',
2510 'SkAutoMaskFreeImage',
2511 'SkAutoMutexAcquire',
2512 'SkAutoPathBoundsUpdate',
2513 'SkAutoPDFRelease',
2514 'SkAutoRasterClipValidate',
2515 'SkAutoRef',
2516 'SkAutoTime',
2517 'SkAutoTrace',
2518 'SkAutoUnref',
2519 ]
2520 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2521 # bad: base::AutoLock(lock.get());
2522 # not bad: base::AutoLock lock(lock.get());
2523 bad_pattern = input_api.re.compile(anonymous)
2524 # good: new base::AutoLock(lock.get())
2525 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2526 errors = []
2527
2528 for f in input_api.AffectedFiles():
2529 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2530 continue
2531 for linenum, line in f.ChangedContents():
2532 if bad_pattern.search(line) and not good_pattern.search(line):
2533 errors.append('%s:%d' % (f.LocalPath(), linenum))
2534
2535 if errors:
2536 return [output_api.PresubmitError(
2537 'These lines create anonymous variables that need to be named:',
2538 items=errors)]
2539 return []
2540
2541
Peter Kasting4844e46e2018-02-23 07:27:102542def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532543 # Returns whether |template_str| is of the form <T, U...> for some types T
2544 # and U. Assumes that |template_str| is already in the form <...>.
2545 def HasMoreThanOneArg(template_str):
2546 # Level of <...> nesting.
2547 nesting = 0
2548 for c in template_str:
2549 if c == '<':
2550 nesting += 1
2551 elif c == '>':
2552 nesting -= 1
2553 elif c == ',' and nesting == 1:
2554 return True
2555 return False
2556
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492557 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102558 sources = lambda affected_file: input_api.FilterSourceFile(
2559 affected_file,
2560 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2561 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492562 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552563
2564 # Pattern to capture a single "<...>" block of template arguments. It can
2565 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2566 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2567 # latter would likely require counting that < and > match, which is not
2568 # expressible in regular languages. Should the need arise, one can introduce
2569 # limited counting (matching up to a total number of nesting depth), which
2570 # should cover all practical cases for already a low nesting limit.
2571 template_arg_pattern = (
2572 r'<[^>]*' # Opening block of <.
2573 r'>([^<]*>)?') # Closing block of >.
2574 # Prefix expressing that whatever follows is not already inside a <...>
2575 # block.
2576 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102577 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552578 not_inside_template_arg_pattern
2579 + r'\bstd::unique_ptr'
2580 + template_arg_pattern
2581 + r'\(\)')
2582
2583 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2584 template_arg_no_array_pattern = (
2585 r'<[^>]*[^]]' # Opening block of <.
2586 r'>([^(<]*[^]]>)?') # Closing block of >.
2587 # Prefix saying that what follows is the start of an expression.
2588 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2589 # Suffix saying that what follows are call parentheses with a non-empty list
2590 # of arguments.
2591 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532592 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552593 return_construct_pattern = input_api.re.compile(
2594 start_of_expr_pattern
2595 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532596 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552597 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532598 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552599 + nonempty_arg_list_pattern)
2600
Vaclav Brozek851d9602018-04-04 16:13:052601 problems_constructor = []
2602 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102603 for f in input_api.AffectedSourceFiles(sources):
2604 for line_number, line in f.ChangedContents():
2605 # Disallow:
2606 # return std::unique_ptr<T>(foo);
2607 # bar = std::unique_ptr<T>(foo);
2608 # But allow:
2609 # return std::unique_ptr<T[]>(foo);
2610 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532611 # And also allow cases when the second template argument is present. Those
2612 # cases cannot be handled by std::make_unique:
2613 # return std::unique_ptr<T, U>(foo);
2614 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052615 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532616 return_construct_result = return_construct_pattern.search(line)
2617 if return_construct_result and not HasMoreThanOneArg(
2618 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052619 problems_constructor.append(
2620 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102621 # Disallow:
2622 # std::unique_ptr<T>()
2623 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052624 problems_nullptr.append(
2625 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2626
2627 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162628 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052629 errors.append(output_api.PresubmitError(
2630 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162631 problems_nullptr))
2632 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052633 errors.append(output_api.PresubmitError(
2634 'The following files use explicit std::unique_ptr constructor.'
2635 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162636 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102637 return errors
2638
2639
[email protected]999261d2014-03-03 20:08:082640def _CheckUserActionUpdate(input_api, output_api):
2641 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522642 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082643 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522644 # If actions.xml is already included in the changelist, the PRESUBMIT
2645 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082646 return []
2647
[email protected]999261d2014-03-03 20:08:082648 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2649 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522650 current_actions = None
[email protected]999261d2014-03-03 20:08:082651 for f in input_api.AffectedFiles(file_filter=file_filter):
2652 for line_num, line in f.ChangedContents():
2653 match = input_api.re.search(action_re, line)
2654 if match:
[email protected]2f92dec2014-03-07 19:21:522655 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2656 # loaded only once.
2657 if not current_actions:
2658 with open('tools/metrics/actions/actions.xml') as actions_f:
2659 current_actions = actions_f.read()
2660 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082661 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522662 action = 'name="{0}"'.format(action_name)
2663 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082664 return [output_api.PresubmitPromptWarning(
2665 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522666 'tools/metrics/actions/actions.xml. Please run '
2667 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082668 % (f.LocalPath(), line_num, action_name))]
2669 return []
2670
2671
Daniel Cheng13ca61a882017-08-25 15:11:252672def _ImportJSONCommentEater(input_api):
2673 import sys
2674 sys.path = sys.path + [input_api.os_path.join(
2675 input_api.PresubmitLocalPath(),
2676 'tools', 'json_comment_eater')]
2677 import json_comment_eater
2678 return json_comment_eater
2679
2680
[email protected]99171a92014-06-03 08:44:472681def _GetJSONParseError(input_api, filename, eat_comments=True):
2682 try:
2683 contents = input_api.ReadFile(filename)
2684 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252685 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132686 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472687
2688 input_api.json.loads(contents)
2689 except ValueError as e:
2690 return e
2691 return None
2692
2693
2694def _GetIDLParseError(input_api, filename):
2695 try:
2696 contents = input_api.ReadFile(filename)
2697 idl_schema = input_api.os_path.join(
2698 input_api.PresubmitLocalPath(),
2699 'tools', 'json_schema_compiler', 'idl_schema.py')
2700 process = input_api.subprocess.Popen(
2701 [input_api.python_executable, idl_schema],
2702 stdin=input_api.subprocess.PIPE,
2703 stdout=input_api.subprocess.PIPE,
2704 stderr=input_api.subprocess.PIPE,
2705 universal_newlines=True)
2706 (_, error) = process.communicate(input=contents)
2707 return error or None
2708 except ValueError as e:
2709 return e
2710
2711
2712def _CheckParseErrors(input_api, output_api):
2713 """Check that IDL and JSON files do not contain syntax errors."""
2714 actions = {
2715 '.idl': _GetIDLParseError,
2716 '.json': _GetJSONParseError,
2717 }
[email protected]99171a92014-06-03 08:44:472718 # Most JSON files are preprocessed and support comments, but these do not.
2719 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042720 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472721 ]
2722 # Only run IDL checker on files in these directories.
2723 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042724 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2725 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472726 ]
2727
2728 def get_action(affected_file):
2729 filename = affected_file.LocalPath()
2730 return actions.get(input_api.os_path.splitext(filename)[1])
2731
[email protected]99171a92014-06-03 08:44:472732 def FilterFile(affected_file):
2733 action = get_action(affected_file)
2734 if not action:
2735 return False
2736 path = affected_file.LocalPath()
2737
Sean Kau46e29bc2017-08-28 16:31:162738 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472739 return False
2740
2741 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162742 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472743 return False
2744 return True
2745
2746 results = []
2747 for affected_file in input_api.AffectedFiles(
2748 file_filter=FilterFile, include_deletes=False):
2749 action = get_action(affected_file)
2750 kwargs = {}
2751 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162752 _MatchesFile(input_api, json_no_comments_patterns,
2753 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472754 kwargs['eat_comments'] = False
2755 parse_error = action(input_api,
2756 affected_file.AbsoluteLocalPath(),
2757 **kwargs)
2758 if parse_error:
2759 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2760 (affected_file.LocalPath(), parse_error)))
2761 return results
2762
2763
[email protected]760deea2013-12-10 19:33:492764def _CheckJavaStyle(input_api, output_api):
2765 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472766 import sys
[email protected]760deea2013-12-10 19:33:492767 original_sys_path = sys.path
2768 try:
2769 sys.path = sys.path + [input_api.os_path.join(
2770 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2771 import checkstyle
2772 finally:
2773 # Restore sys.path to what it was before.
2774 sys.path = original_sys_path
2775
2776 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092777 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512778 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492779
2780
Nate Fischerdfd9812e2019-07-18 22:03:002781def _CheckPythonDevilInit(input_api, output_api):
2782 """Checks to make sure devil is initialized correctly in python scripts."""
2783 script_common_initialize_pattern = input_api.re.compile(
2784 r'script_common\.InitializeEnvironment\(')
2785 devil_env_config_initialize = input_api.re.compile(
2786 r'devil_env\.config\.Initialize\(')
2787
2788 errors = []
2789
2790 sources = lambda affected_file: input_api.FilterSourceFile(
2791 affected_file,
2792 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2793 (r'^build[\\/]android[\\/]devil_chromium\.py',
2794 r'^third_party[\\/].*',)),
2795 white_list=[r'.*\.py$'])
2796
2797 for f in input_api.AffectedSourceFiles(sources):
2798 for line_num, line in f.ChangedContents():
2799 if (script_common_initialize_pattern.search(line) or
2800 devil_env_config_initialize.search(line)):
2801 errors.append("%s:%d" % (f.LocalPath(), line_num))
2802
2803 results = []
2804
2805 if errors:
2806 results.append(output_api.PresubmitError(
2807 'Devil initialization should always be done using '
2808 'devil_chromium.Initialize() in the chromium project, to use better '
2809 'defaults for dependencies (ex. up-to-date version of adb).',
2810 errors))
2811
2812 return results
2813
2814
Sean Kau46e29bc2017-08-28 16:31:162815def _MatchesFile(input_api, patterns, path):
2816 for pattern in patterns:
2817 if input_api.re.search(pattern, path):
2818 return True
2819 return False
2820
2821
Daniel Cheng7052cdf2017-11-21 19:23:292822def _GetOwnersFilesToCheckForIpcOwners(input_api):
2823 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172824
Daniel Cheng7052cdf2017-11-21 19:23:292825 Returns:
2826 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2827 contain to cover IPC-related files with noparent reviewer rules.
2828 """
2829 # Whether or not a file affects IPC is (mostly) determined by a simple list
2830 # of filename patterns.
dchenge07de812016-06-20 19:27:172831 file_patterns = [
palmerb19a0932017-01-24 04:00:312832 # Legacy IPC:
dchenge07de812016-06-20 19:27:172833 '*_messages.cc',
2834 '*_messages*.h',
2835 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312836 # Mojo IPC:
dchenge07de812016-06-20 19:27:172837 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472838 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172839 '*_struct_traits*.*',
2840 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312841 '*.typemap',
2842 # Android native IPC:
2843 '*.aidl',
2844 # Blink uses a different file naming convention:
2845 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472846 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172847 '*StructTraits*.*',
2848 '*TypeConverter*.*',
2849 ]
2850
scottmg7a6ed5ba2016-11-04 18:22:042851 # These third_party directories do not contain IPCs, but contain files
2852 # matching the above patterns, which trigger false positives.
2853 exclude_paths = [
2854 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162855 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232856 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292857 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542858 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162859 # These files are just used to communicate between class loaders running
2860 # in the same process.
2861 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572862 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2863
scottmg7a6ed5ba2016-11-04 18:22:042864 ]
2865
dchenge07de812016-06-20 19:27:172866 # Dictionary mapping an OWNERS file path to Patterns.
2867 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2868 # rules ) to a PatternEntry.
2869 # PatternEntry is a dictionary with two keys:
2870 # - 'files': the files that are matched by this pattern
2871 # - 'rules': the per-file rules needed for this pattern
2872 # For example, if we expect OWNERS file to contain rules for *.mojom and
2873 # *_struct_traits*.*, Patterns might look like this:
2874 # {
2875 # '*.mojom': {
2876 # 'files': ...,
2877 # 'rules': [
2878 # 'per-file *.mojom=set noparent',
2879 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2880 # ],
2881 # },
2882 # '*_struct_traits*.*': {
2883 # 'files': ...,
2884 # 'rules': [
2885 # 'per-file *_struct_traits*.*=set noparent',
2886 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2887 # ],
2888 # },
2889 # }
2890 to_check = {}
2891
Daniel Cheng13ca61a882017-08-25 15:11:252892 def AddPatternToCheck(input_file, pattern):
2893 owners_file = input_api.os_path.join(
2894 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2895 if owners_file not in to_check:
2896 to_check[owners_file] = {}
2897 if pattern not in to_check[owners_file]:
2898 to_check[owners_file][pattern] = {
2899 'files': [],
2900 'rules': [
2901 'per-file %s=set noparent' % pattern,
2902 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2903 ]
2904 }
Vaclav Brozekd5de76a2018-03-17 07:57:502905 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252906
dchenge07de812016-06-20 19:27:172907 # Iterate through the affected files to see what we actually need to check
2908 # for. We should only nag patch authors about per-file rules if a file in that
2909 # directory would match that pattern. If a directory only contains *.mojom
2910 # files and no *_messages*.h files, we should only nag about rules for
2911 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252912 for f in input_api.AffectedFiles(include_deletes=False):
2913 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362914 # affected files for .json, .cc, and .h files which look like they contain
2915 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162916 if (f.LocalPath().endswith('.json') and
2917 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2918 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252919 json_comment_eater = _ImportJSONCommentEater(input_api)
2920 mostly_json_lines = '\n'.join(f.NewContents())
2921 # Comments aren't allowed in strict JSON, so filter them out.
2922 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432923 try:
2924 json_content = input_api.json.loads(json_lines)
2925 except:
2926 # There's another PRESUBMIT check that already verifies that JSON files
2927 # are not invalid, so no need to emit another warning here.
2928 continue
Daniel Cheng13ca61a882017-08-25 15:11:252929 if 'interface_provider_specs' in json_content:
2930 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362931 else:
2932 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2933 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2934 if (manifest_pattern.search(f.LocalPath()) and not
2935 test_manifest_pattern.search(f.LocalPath())):
2936 # We expect all actual service manifest files to contain at least one
2937 # qualified reference to service_manager::Manifest.
2938 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2939 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172940 for pattern in file_patterns:
2941 if input_api.fnmatch.fnmatch(
2942 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042943 skip = False
2944 for exclude in exclude_paths:
2945 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2946 skip = True
2947 break
2948 if skip:
2949 continue
Daniel Cheng13ca61a882017-08-25 15:11:252950 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172951 break
2952
Daniel Cheng7052cdf2017-11-21 19:23:292953 return to_check
2954
2955
2956def _CheckIpcOwners(input_api, output_api):
2957 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2958 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2959
2960 if to_check:
2961 # If there are any OWNERS files to check, there are IPC-related changes in
2962 # this CL. Auto-CC the review list.
2963 output_api.AppendCC('[email protected]')
2964
2965 # Go through the OWNERS files to check, filtering out rules that are already
2966 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172967 for owners_file, patterns in to_check.iteritems():
2968 try:
2969 with file(owners_file) as f:
2970 lines = set(f.read().splitlines())
2971 for entry in patterns.itervalues():
2972 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2973 ]
2974 except IOError:
2975 # No OWNERS file, so all the rules are definitely missing.
2976 continue
2977
2978 # All the remaining lines weren't found in OWNERS files, so emit an error.
2979 errors = []
2980 for owners_file, patterns in to_check.iteritems():
2981 missing_lines = []
2982 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502983 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172984 missing_lines.extend(entry['rules'])
2985 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2986 if missing_lines:
2987 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:052988 'Because of the presence of files:\n%s\n\n'
2989 '%s needs the following %d lines added:\n\n%s' %
2990 ('\n'.join(files), owners_file, len(missing_lines),
2991 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:172992
2993 results = []
2994 if errors:
vabrf5ce3bf92016-07-11 14:52:412995 if input_api.is_committing:
2996 output = output_api.PresubmitError
2997 else:
2998 output = output_api.PresubmitPromptWarning
2999 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593000 'Found OWNERS files that need to be updated for IPC security ' +
3001 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173002 long_text='\n\n'.join(errors)))
3003
3004 return results
3005
3006
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263007def _CheckSetNoParent(input_api, output_api):
3008 """Checks that set noparent is only used together with an OWNERS file in
3009 //build/OWNERS.setnoparent (see also
3010 //docs/code_reviews.md#owners-files-details)
3011 """
3012 errors = []
3013
3014 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3015 allowed_owners_files = set()
3016 with open(allowed_owners_files_file, 'r') as f:
3017 for line in f:
3018 line = line.strip()
3019 if not line or line.startswith('#'):
3020 continue
3021 allowed_owners_files.add(line)
3022
3023 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3024
3025 for f in input_api.AffectedFiles(include_deletes=False):
3026 if not f.LocalPath().endswith('OWNERS'):
3027 continue
3028
3029 found_owners_files = set()
3030 found_set_noparent_lines = dict()
3031
3032 # Parse the OWNERS file.
3033 for lineno, line in enumerate(f.NewContents(), 1):
3034 line = line.strip()
3035 if line.startswith('set noparent'):
3036 found_set_noparent_lines[''] = lineno
3037 if line.startswith('file://'):
3038 if line in allowed_owners_files:
3039 found_owners_files.add('')
3040 if line.startswith('per-file'):
3041 match = per_file_pattern.match(line)
3042 if match:
3043 glob = match.group(1).strip()
3044 directive = match.group(2).strip()
3045 if directive == 'set noparent':
3046 found_set_noparent_lines[glob] = lineno
3047 if directive.startswith('file://'):
3048 if directive in allowed_owners_files:
3049 found_owners_files.add(glob)
3050
3051 # Check that every set noparent line has a corresponding file:// line
3052 # listed in build/OWNERS.setnoparent.
3053 for set_noparent_line in found_set_noparent_lines:
3054 if set_noparent_line in found_owners_files:
3055 continue
3056 errors.append(' %s:%d' % (f.LocalPath(),
3057 found_set_noparent_lines[set_noparent_line]))
3058
3059 results = []
3060 if errors:
3061 if input_api.is_committing:
3062 output = output_api.PresubmitError
3063 else:
3064 output = output_api.PresubmitPromptWarning
3065 results.append(output(
3066 'Found the following "set noparent" restrictions in OWNERS files that '
3067 'do not include owners from build/OWNERS.setnoparent:',
3068 long_text='\n\n'.join(errors)))
3069 return results
3070
3071
jbriance9e12f162016-11-25 07:57:503072def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313073 """Checks that added or removed lines in non third party affected
3074 header files do not lead to new useless class or struct forward
3075 declaration.
jbriance9e12f162016-11-25 07:57:503076 """
3077 results = []
3078 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3079 input_api.re.MULTILINE)
3080 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3081 input_api.re.MULTILINE)
3082 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313083 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193084 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493085 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313086 continue
3087
jbriance9e12f162016-11-25 07:57:503088 if not f.LocalPath().endswith('.h'):
3089 continue
3090
3091 contents = input_api.ReadFile(f)
3092 fwd_decls = input_api.re.findall(class_pattern, contents)
3093 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3094
3095 useless_fwd_decls = []
3096 for decl in fwd_decls:
3097 count = sum(1 for _ in input_api.re.finditer(
3098 r'\b%s\b' % input_api.re.escape(decl), contents))
3099 if count == 1:
3100 useless_fwd_decls.append(decl)
3101
3102 if not useless_fwd_decls:
3103 continue
3104
3105 for line in f.GenerateScmDiff().splitlines():
3106 if (line.startswith('-') and not line.startswith('--') or
3107 line.startswith('+') and not line.startswith('++')):
3108 for decl in useless_fwd_decls:
3109 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3110 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243111 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503112 (f.LocalPath(), decl)))
3113 useless_fwd_decls.remove(decl)
3114
3115 return results
3116
Jinsong Fan91ebbbd2019-04-16 14:57:173117def _CheckAndroidDebuggableBuild(input_api, output_api):
3118 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3119 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3120 this is a debuggable build of Android.
3121 """
3122 build_type_check_pattern = input_api.re.compile(
3123 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3124
3125 errors = []
3126
3127 sources = lambda affected_file: input_api.FilterSourceFile(
3128 affected_file,
3129 black_list=(_EXCLUDED_PATHS +
3130 _TEST_CODE_EXCLUDED_PATHS +
3131 input_api.DEFAULT_BLACK_LIST +
3132 (r"^android_webview[\\/]support_library[\\/]"
3133 "boundary_interfaces[\\/]",
3134 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3135 r'^third_party[\\/].*',
3136 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3137 r"webview[\\/]chromium[\\/]License.*",)),
3138 white_list=[r'.*\.java$'])
3139
3140 for f in input_api.AffectedSourceFiles(sources):
3141 for line_num, line in f.ChangedContents():
3142 if build_type_check_pattern.search(line):
3143 errors.append("%s:%d" % (f.LocalPath(), line_num))
3144
3145 results = []
3146
3147 if errors:
3148 results.append(output_api.PresubmitPromptWarning(
3149 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3150 ' Please use BuildInfo.isDebugAndroid() instead.',
3151 errors))
3152
3153 return results
jbriance9e12f162016-11-25 07:57:503154
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493155# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293156def _CheckAndroidToastUsage(input_api, output_api):
3157 """Checks that code uses org.chromium.ui.widget.Toast instead of
3158 android.widget.Toast (Chromium Toast doesn't force hardware
3159 acceleration on low-end devices, saving memory).
3160 """
3161 toast_import_pattern = input_api.re.compile(
3162 r'^import android\.widget\.Toast;$')
3163
3164 errors = []
3165
3166 sources = lambda affected_file: input_api.FilterSourceFile(
3167 affected_file,
3168 black_list=(_EXCLUDED_PATHS +
3169 _TEST_CODE_EXCLUDED_PATHS +
3170 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043171 (r'^chromecast[\\/].*',
3172 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493173 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293174
3175 for f in input_api.AffectedSourceFiles(sources):
3176 for line_num, line in f.ChangedContents():
3177 if toast_import_pattern.search(line):
3178 errors.append("%s:%d" % (f.LocalPath(), line_num))
3179
3180 results = []
3181
3182 if errors:
3183 results.append(output_api.PresubmitError(
3184 'android.widget.Toast usage is detected. Android toasts use hardware'
3185 ' acceleration, and can be\ncostly on low-end devices. Please use'
3186 ' org.chromium.ui.widget.Toast instead.\n'
3187 'Contact [email protected] if you have any questions.',
3188 errors))
3189
3190 return results
3191
3192
dgnaa68d5e2015-06-10 10:08:223193def _CheckAndroidCrLogUsage(input_api, output_api):
3194 """Checks that new logs using org.chromium.base.Log:
3195 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513196 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223197 """
pkotwicza1dd0b002016-05-16 14:41:043198
torne89540622017-03-24 19:41:303199 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043200 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303201 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043202 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303203 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043204 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3205 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093206 # The customtabs_benchmark is a small app that does not depend on Chromium
3207 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043208 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043209 ]
3210
dgnaa68d5e2015-06-10 10:08:223211 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123212 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3213 class_in_base_pattern = input_api.re.compile(
3214 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3215 has_some_log_import_pattern = input_api.re.compile(
3216 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223217 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123218 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223219 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463220 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223221
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463222 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493223 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043224 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123225
dgnaa68d5e2015-06-10 10:08:223226 tag_decl_errors = []
3227 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123228 tag_errors = []
dgn38736db2015-09-18 19:20:513229 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123230 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223231
3232 for f in input_api.AffectedSourceFiles(sources):
3233 file_content = input_api.ReadFile(f)
3234 has_modified_logs = False
3235
3236 # Per line checks
dgn87d9fb62015-06-12 09:15:123237 if (cr_log_import_pattern.search(file_content) or
3238 (class_in_base_pattern.search(file_content) and
3239 not has_some_log_import_pattern.search(file_content))):
3240 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223241 for line_num, line in f.ChangedContents():
3242
3243 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123244 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223245 if match:
3246 has_modified_logs = True
3247
3248 # Make sure it uses "TAG"
3249 if not match.group('tag') == 'TAG':
3250 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123251 else:
3252 # Report non cr Log function calls in changed lines
3253 for line_num, line in f.ChangedContents():
3254 if log_call_pattern.search(line):
3255 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223256
3257 # Per file checks
3258 if has_modified_logs:
3259 # Make sure the tag is using the "cr" prefix and is not too long
3260 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513261 tag_name = match.group('name') if match else None
3262 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223263 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513264 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223265 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513266 elif '.' in tag_name:
3267 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223268
3269 results = []
3270 if tag_decl_errors:
3271 results.append(output_api.PresubmitPromptWarning(
3272 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513273 '"private static final String TAG = "<package tag>".\n'
3274 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223275 tag_decl_errors))
3276
3277 if tag_length_errors:
3278 results.append(output_api.PresubmitError(
3279 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513280 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223281 tag_length_errors))
3282
3283 if tag_errors:
3284 results.append(output_api.PresubmitPromptWarning(
3285 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3286 tag_errors))
3287
dgn87d9fb62015-06-12 09:15:123288 if util_log_errors:
dgn4401aa52015-04-29 16:26:173289 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123290 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3291 util_log_errors))
3292
dgn38736db2015-09-18 19:20:513293 if tag_with_dot_errors:
3294 results.append(output_api.PresubmitPromptWarning(
3295 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3296 tag_with_dot_errors))
3297
dgn4401aa52015-04-29 16:26:173298 return results
3299
3300
Yoland Yanb92fa522017-08-28 17:37:063301def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3302 """Checks that junit.framework.* is no longer used."""
3303 deprecated_junit_framework_pattern = input_api.re.compile(
3304 r'^import junit\.framework\..*;',
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)
Yoland Yanb92fa522017-08-28 17:37:063308 errors = []
3309 for f in input_api.AffectedFiles(sources):
3310 for line_num, line in f.ChangedContents():
3311 if deprecated_junit_framework_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 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3318 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3319 ' if you have any question.', errors))
3320 return results
3321
3322
3323def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3324 """Checks that if new Java test classes have inheritance.
3325 Either the new test class is JUnit3 test or it is a JUnit4 test class
3326 with a base class, either case is undesirable.
3327 """
3328 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3329
3330 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493331 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063332 errors = []
3333 for f in input_api.AffectedFiles(sources):
3334 if not f.OldContents():
3335 class_declaration_start_flag = False
3336 for line_num, line in f.ChangedContents():
3337 if class_declaration_pattern.search(line):
3338 class_declaration_start_flag = True
3339 if class_declaration_start_flag and ' extends ' in line:
3340 errors.append('%s:%d' % (f.LocalPath(), line_num))
3341 if '{' in line:
3342 class_declaration_start_flag = False
3343
3344 results = []
3345 if errors:
3346 results.append(output_api.PresubmitPromptWarning(
3347 'The newly created files include Test classes that inherits from base'
3348 ' class. Please do not use inheritance in JUnit4 tests or add new'
3349 ' JUnit3 tests. Contact [email protected] if you have any'
3350 ' questions.', errors))
3351 return results
3352
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203353
yolandyan45001472016-12-21 21:12:423354def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3355 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3356 deprecated_annotation_import_pattern = input_api.re.compile(
3357 r'^import android\.test\.suitebuilder\.annotation\..*;',
3358 input_api.re.MULTILINE)
3359 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493360 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423361 errors = []
3362 for f in input_api.AffectedFiles(sources):
3363 for line_num, line in f.ChangedContents():
3364 if deprecated_annotation_import_pattern.search(line):
3365 errors.append("%s:%d" % (f.LocalPath(), line_num))
3366
3367 results = []
3368 if errors:
3369 results.append(output_api.PresubmitError(
3370 'Annotations in android.test.suitebuilder.annotation have been'
3371 ' deprecated since API level 24. Please use android.support.test.filters'
3372 ' from //third_party/android_support_test_runner:runner_java instead.'
3373 ' Contact [email protected] if you have any questions.', errors))
3374 return results
3375
3376
agrieve7b6479d82015-10-07 14:24:223377def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3378 """Checks if MDPI assets are placed in a correct directory."""
3379 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3380 ('/res/drawable/' in f.LocalPath() or
3381 '/res/drawable-ldrtl/' in f.LocalPath()))
3382 errors = []
3383 for f in input_api.AffectedFiles(include_deletes=False,
3384 file_filter=file_filter):
3385 errors.append(' %s' % f.LocalPath())
3386
3387 results = []
3388 if errors:
3389 results.append(output_api.PresubmitError(
3390 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3391 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3392 '/res/drawable-ldrtl/.\n'
3393 'Contact [email protected] if you have questions.', errors))
3394 return results
3395
3396
Nate Fischer535972b2017-09-16 01:06:183397def _CheckAndroidWebkitImports(input_api, output_api):
3398 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353399 android.webview.ValueCallback except in the WebView glue layer
3400 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183401 """
3402 valuecallback_import_pattern = input_api.re.compile(
3403 r'^import android\.webkit\.ValueCallback;$')
3404
3405 errors = []
3406
3407 sources = lambda affected_file: input_api.FilterSourceFile(
3408 affected_file,
3409 black_list=(_EXCLUDED_PATHS +
3410 _TEST_CODE_EXCLUDED_PATHS +
3411 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353412 (r'^android_webview[\\/]glue[\\/].*',
3413 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493414 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183415
3416 for f in input_api.AffectedSourceFiles(sources):
3417 for line_num, line in f.ChangedContents():
3418 if valuecallback_import_pattern.search(line):
3419 errors.append("%s:%d" % (f.LocalPath(), line_num))
3420
3421 results = []
3422
3423 if errors:
3424 results.append(output_api.PresubmitError(
3425 'android.webkit.ValueCallback usage is detected outside of the glue'
3426 ' layer. To stay compatible with the support library, android.webkit.*'
3427 ' classes should only be used inside the glue layer and'
3428 ' org.chromium.base.Callback should be used instead.',
3429 errors))
3430
3431 return results
3432
3433
Becky Zhou7c69b50992018-12-10 19:37:573434def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3435 """Checks Android XML styles """
3436 import sys
3437 original_sys_path = sys.path
3438 try:
3439 sys.path = sys.path + [input_api.os_path.join(
3440 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3441 import checkxmlstyle
3442 finally:
3443 # Restore sys.path to what it was before.
3444 sys.path = original_sys_path
3445
3446 if is_check_on_upload:
3447 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3448 else:
3449 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3450
3451
agrievef32bcc72016-04-04 14:57:403452class PydepsChecker(object):
3453 def __init__(self, input_api, pydeps_files):
3454 self._file_cache = {}
3455 self._input_api = input_api
3456 self._pydeps_files = pydeps_files
3457
3458 def _LoadFile(self, path):
3459 """Returns the list of paths within a .pydeps file relative to //."""
3460 if path not in self._file_cache:
3461 with open(path) as f:
3462 self._file_cache[path] = f.read()
3463 return self._file_cache[path]
3464
3465 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3466 """Returns an interable of paths within the .pydep, relativized to //."""
3467 os_path = self._input_api.os_path
3468 pydeps_dir = os_path.dirname(pydeps_path)
3469 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3470 if not l.startswith('*'))
3471 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3472
3473 def _CreateFilesToPydepsMap(self):
3474 """Returns a map of local_path -> list_of_pydeps."""
3475 ret = {}
3476 for pydep_local_path in self._pydeps_files:
3477 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3478 ret.setdefault(path, []).append(pydep_local_path)
3479 return ret
3480
3481 def ComputeAffectedPydeps(self):
3482 """Returns an iterable of .pydeps files that might need regenerating."""
3483 affected_pydeps = set()
3484 file_to_pydeps_map = None
3485 for f in self._input_api.AffectedFiles(include_deletes=True):
3486 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463487 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3488 # subrepositories. We can't figure out which files change, so re-check
3489 # all files.
3490 # Changes to print_python_deps.py affect all .pydeps.
3491 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403492 return self._pydeps_files
3493 elif local_path.endswith('.pydeps'):
3494 if local_path in self._pydeps_files:
3495 affected_pydeps.add(local_path)
3496 elif local_path.endswith('.py'):
3497 if file_to_pydeps_map is None:
3498 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3499 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3500 return affected_pydeps
3501
3502 def DetermineIfStale(self, pydeps_path):
3503 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413504 import difflib
John Budorick47ca3fe2018-02-10 00:53:103505 import os
3506
agrievef32bcc72016-04-04 14:57:403507 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3508 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103509 env = dict(os.environ)
3510 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403511 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103512 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413513 old_contents = old_pydeps_data[2:]
3514 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403515 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413516 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403517
3518
Tibor Goldschwendt360793f72019-06-25 18:23:493519def _ParseGclientArgs():
3520 args = {}
3521 with open('build/config/gclient_args.gni', 'r') as f:
3522 for line in f:
3523 line = line.strip()
3524 if not line or line.startswith('#'):
3525 continue
3526 attribute, value = line.split('=')
3527 args[attribute.strip()] = value.strip()
3528 return args
3529
3530
agrievef32bcc72016-04-04 14:57:403531def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3532 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403533 # This check is for Python dependency lists (.pydeps files), and involves
3534 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3535 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283536 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003537 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493538 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403539 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3540 results = []
3541 # First, check for new / deleted .pydeps.
3542 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033543 # Check whether we are running the presubmit check for a file in src.
3544 # f.LocalPath is relative to repo (src, or internal repo).
3545 # os_path.exists is relative to src repo.
3546 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3547 # to src and we can conclude that the pydeps is in src.
3548 if input_api.os_path.exists(f.LocalPath()):
3549 if f.LocalPath().endswith('.pydeps'):
3550 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3551 results.append(output_api.PresubmitError(
3552 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3553 'remove %s' % f.LocalPath()))
3554 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3555 results.append(output_api.PresubmitError(
3556 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3557 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403558
3559 if results:
3560 return results
3561
3562 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3563
3564 for pydep_path in checker.ComputeAffectedPydeps():
3565 try:
phajdan.jr0d9878552016-11-04 10:49:413566 result = checker.DetermineIfStale(pydep_path)
3567 if result:
3568 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403569 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413570 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3571 'To regenerate, run:\n\n %s' %
3572 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403573 except input_api.subprocess.CalledProcessError as error:
3574 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3575 long_text=error.output)]
3576
3577 return results
3578
3579
glidere61efad2015-02-18 17:39:433580def _CheckSingletonInHeaders(input_api, output_api):
3581 """Checks to make sure no header files have |Singleton<|."""
3582 def FileFilter(affected_file):
3583 # It's ok for base/memory/singleton.h to have |Singleton<|.
3584 black_list = (_EXCLUDED_PATHS +
3585 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043586 (r"^base[\\/]memory[\\/]singleton\.h$",
3587 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473588 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433589 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3590
sergeyu34d21222015-09-16 00:11:443591 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433592 files = []
3593 for f in input_api.AffectedSourceFiles(FileFilter):
3594 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3595 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3596 contents = input_api.ReadFile(f)
3597 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243598 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433599 pattern.search(line)):
3600 files.append(f)
3601 break
3602
3603 if files:
yolandyandaabc6d2016-04-18 18:29:393604 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443605 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433606 'Please move them to an appropriate source file so that the ' +
3607 'template gets instantiated in a single compilation unit.',
3608 files) ]
3609 return []
3610
3611
[email protected]fd20b902014-05-09 02:14:533612_DEPRECATED_CSS = [
3613 # Values
3614 ( "-webkit-box", "flex" ),
3615 ( "-webkit-inline-box", "inline-flex" ),
3616 ( "-webkit-flex", "flex" ),
3617 ( "-webkit-inline-flex", "inline-flex" ),
3618 ( "-webkit-min-content", "min-content" ),
3619 ( "-webkit-max-content", "max-content" ),
3620
3621 # Properties
3622 ( "-webkit-background-clip", "background-clip" ),
3623 ( "-webkit-background-origin", "background-origin" ),
3624 ( "-webkit-background-size", "background-size" ),
3625 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443626 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533627
3628 # Functions
3629 ( "-webkit-gradient", "gradient" ),
3630 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3631 ( "-webkit-linear-gradient", "linear-gradient" ),
3632 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3633 ( "-webkit-radial-gradient", "radial-gradient" ),
3634 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3635]
3636
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203637
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493638# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243639def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533640 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253641 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343642 documentation and iOS CSS for dom distiller
3643 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253644 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533645 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493646 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253647 black_list = (_EXCLUDED_PATHS +
3648 _TEST_CODE_EXCLUDED_PATHS +
3649 input_api.DEFAULT_BLACK_LIST +
3650 (r"^chrome/common/extensions/docs",
3651 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343652 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443653 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253654 r"^native_client_sdk"))
3655 file_filter = lambda f: input_api.FilterSourceFile(
3656 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533657 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3658 for line_num, line in fpath.ChangedContents():
3659 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023660 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533661 results.append(output_api.PresubmitError(
3662 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3663 (fpath.LocalPath(), line_num, deprecated_value, value)))
3664 return results
3665
mohan.reddyf21db962014-10-16 12:26:473666
rlanday6802cf632017-05-30 17:48:363667def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363668 bad_files = {}
3669 for f in input_api.AffectedFiles(include_deletes=False):
3670 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493671 not f.LocalPath().startswith('third_party/blink') and
3672 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363673 continue
3674
Daniel Bratell65b033262019-04-23 08:17:063675 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363676 continue
3677
Vaclav Brozekd5de76a2018-03-17 07:57:503678 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363679 if "#include" in line and "../" in line]
3680 if not relative_includes:
3681 continue
3682 bad_files[f.LocalPath()] = relative_includes
3683
3684 if not bad_files:
3685 return []
3686
3687 error_descriptions = []
3688 for file_path, bad_lines in bad_files.iteritems():
3689 error_description = file_path
3690 for line in bad_lines:
3691 error_description += '\n ' + line
3692 error_descriptions.append(error_description)
3693
3694 results = []
3695 results.append(output_api.PresubmitError(
3696 'You added one or more relative #include paths (including "../").\n'
3697 'These shouldn\'t be used because they can be used to include headers\n'
3698 'from code that\'s not correctly specified as a dependency in the\n'
3699 'relevant BUILD.gn file(s).',
3700 error_descriptions))
3701
3702 return results
3703
Takeshi Yoshinoe387aa32017-08-02 13:16:133704
Daniel Bratell65b033262019-04-23 08:17:063705def _CheckForCcIncludes(input_api, output_api):
3706 """Check that nobody tries to include a cc file. It's a relatively
3707 common error which results in duplicate symbols in object
3708 files. This may not always break the build until someone later gets
3709 very confusing linking errors."""
3710 results = []
3711 for f in input_api.AffectedFiles(include_deletes=False):
3712 # We let third_party code do whatever it wants
3713 if (f.LocalPath().startswith('third_party') and
3714 not f.LocalPath().startswith('third_party/blink') and
3715 not f.LocalPath().startswith('third_party\\blink')):
3716 continue
3717
3718 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3719 continue
3720
3721 for _, line in f.ChangedContents():
3722 if line.startswith('#include "'):
3723 included_file = line.split('"')[1]
3724 if _IsCPlusPlusFile(input_api, included_file):
3725 # The most common naming for external files with C++ code,
3726 # apart from standard headers, is to call them foo.inc, but
3727 # Chromium sometimes uses foo-inc.cc so allow that as well.
3728 if not included_file.endswith(('.h', '-inc.cc')):
3729 results.append(output_api.PresubmitError(
3730 'Only header files or .inc files should be included in other\n'
3731 'C++ files. Compiling the contents of a cc file more than once\n'
3732 'will cause duplicate information in the build which may later\n'
3733 'result in strange link_errors.\n' +
3734 f.LocalPath() + ':\n ' +
3735 line))
3736
3737 return results
3738
3739
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203740def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3741 if not isinstance(key, ast.Str):
3742 return 'Key at line %d must be a string literal' % key.lineno
3743 if not isinstance(value, ast.Dict):
3744 return 'Value at line %d must be a dict' % value.lineno
3745 if len(value.keys) != 1:
3746 return 'Dict at line %d must have single entry' % value.lineno
3747 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3748 return (
3749 'Entry at line %d must have a string literal \'filepath\' as key' %
3750 value.lineno)
3751 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133752
Takeshi Yoshinoe387aa32017-08-02 13:16:133753
Sergey Ulanov4af16052018-11-08 02:41:463754def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203755 if not isinstance(key, ast.Str):
3756 return 'Key at line %d must be a string literal' % key.lineno
3757 if not isinstance(value, ast.List):
3758 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463759 for element in value.elts:
3760 if not isinstance(element, ast.Str):
3761 return 'Watchlist elements on line %d is not a string' % key.lineno
3762 if not email_regex.match(element.s):
3763 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3764 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203765 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133766
Takeshi Yoshinoe387aa32017-08-02 13:16:133767
Sergey Ulanov4af16052018-11-08 02:41:463768def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203769 mismatch_template = (
3770 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3771 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133772
Sergey Ulanov4af16052018-11-08 02:41:463773 email_regex = input_api.re.compile(
3774 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3775
3776 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203777 i = 0
3778 last_key = ''
3779 while True:
3780 if i >= len(wd_dict.keys):
3781 if i >= len(w_dict.keys):
3782 return None
3783 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3784 elif i >= len(w_dict.keys):
3785 return (
3786 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133787
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203788 wd_key = wd_dict.keys[i]
3789 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133790
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203791 result = _CheckWatchlistDefinitionsEntrySyntax(
3792 wd_key, wd_dict.values[i], ast)
3793 if result is not None:
3794 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133795
Sergey Ulanov4af16052018-11-08 02:41:463796 result = _CheckWatchlistsEntrySyntax(
3797 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203798 if result is not None:
3799 return 'Bad entry in WATCHLISTS dict: %s' % result
3800
3801 if wd_key.s != w_key.s:
3802 return mismatch_template % (
3803 '%s at line %d' % (wd_key.s, wd_key.lineno),
3804 '%s at line %d' % (w_key.s, w_key.lineno))
3805
3806 if wd_key.s < last_key:
3807 return (
3808 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3809 (wd_key.lineno, w_key.lineno))
3810 last_key = wd_key.s
3811
3812 i = i + 1
3813
3814
Sergey Ulanov4af16052018-11-08 02:41:463815def _CheckWATCHLISTSSyntax(expression, input_api):
3816 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203817 if not isinstance(expression, ast.Expression):
3818 return 'WATCHLISTS file must contain a valid expression'
3819 dictionary = expression.body
3820 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3821 return 'WATCHLISTS file must have single dict with exactly two entries'
3822
3823 first_key = dictionary.keys[0]
3824 first_value = dictionary.values[0]
3825 second_key = dictionary.keys[1]
3826 second_value = dictionary.values[1]
3827
3828 if (not isinstance(first_key, ast.Str) or
3829 first_key.s != 'WATCHLIST_DEFINITIONS' or
3830 not isinstance(first_value, ast.Dict)):
3831 return (
3832 'The first entry of the dict in WATCHLISTS file must be '
3833 'WATCHLIST_DEFINITIONS dict')
3834
3835 if (not isinstance(second_key, ast.Str) or
3836 second_key.s != 'WATCHLISTS' or
3837 not isinstance(second_value, ast.Dict)):
3838 return (
3839 'The second entry of the dict in WATCHLISTS file must be '
3840 'WATCHLISTS dict')
3841
Sergey Ulanov4af16052018-11-08 02:41:463842 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133843
3844
3845def _CheckWATCHLISTS(input_api, output_api):
3846 for f in input_api.AffectedFiles(include_deletes=False):
3847 if f.LocalPath() == 'WATCHLISTS':
3848 contents = input_api.ReadFile(f, 'r')
3849
3850 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203851 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133852 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203853 # Get an AST tree for it and scan the tree for detailed style checking.
3854 expression = input_api.ast.parse(
3855 contents, filename='WATCHLISTS', mode='eval')
3856 except ValueError as e:
3857 return [output_api.PresubmitError(
3858 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3859 except SyntaxError as e:
3860 return [output_api.PresubmitError(
3861 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3862 except TypeError as e:
3863 return [output_api.PresubmitError(
3864 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133865
Sergey Ulanov4af16052018-11-08 02:41:463866 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203867 if result is not None:
3868 return [output_api.PresubmitError(result)]
3869 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133870
3871 return []
3872
3873
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193874def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3875 """Checks that newly added header files have corresponding GN changes.
3876 Note that this is only a heuristic. To be precise, run script:
3877 build/check_gn_headers.py.
3878 """
3879
3880 def headers(f):
3881 return input_api.FilterSourceFile(
3882 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3883
3884 new_headers = []
3885 for f in input_api.AffectedSourceFiles(headers):
3886 if f.Action() != 'A':
3887 continue
3888 new_headers.append(f.LocalPath())
3889
3890 def gn_files(f):
3891 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3892
3893 all_gn_changed_contents = ''
3894 for f in input_api.AffectedSourceFiles(gn_files):
3895 for _, line in f.ChangedContents():
3896 all_gn_changed_contents += line
3897
3898 problems = []
3899 for header in new_headers:
3900 basename = input_api.os_path.basename(header)
3901 if basename not in all_gn_changed_contents:
3902 problems.append(header)
3903
3904 if problems:
3905 return [output_api.PresubmitPromptWarning(
3906 'Missing GN changes for new header files', items=sorted(problems),
3907 long_text='Please double check whether newly added header files need '
3908 'corresponding changes in gn or gni files.\nThis checking is only a '
3909 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3910 'Read https://crbug.com/661774 for more info.')]
3911 return []
3912
3913
Michael Giuffridad3bc8672018-10-25 22:48:023914def _CheckCorrectProductNameInMessages(input_api, output_api):
3915 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3916
3917 This assumes we won't intentionally reference one product from the other
3918 product.
3919 """
3920 all_problems = []
3921 test_cases = [{
3922 "filename_postfix": "google_chrome_strings.grd",
3923 "correct_name": "Chrome",
3924 "incorrect_name": "Chromium",
3925 }, {
3926 "filename_postfix": "chromium_strings.grd",
3927 "correct_name": "Chromium",
3928 "incorrect_name": "Chrome",
3929 }]
3930
3931 for test_case in test_cases:
3932 problems = []
3933 filename_filter = lambda x: x.LocalPath().endswith(
3934 test_case["filename_postfix"])
3935
3936 # Check each new line. Can yield false positives in multiline comments, but
3937 # easier than trying to parse the XML because messages can have nested
3938 # children, and associating message elements with affected lines is hard.
3939 for f in input_api.AffectedSourceFiles(filename_filter):
3940 for line_num, line in f.ChangedContents():
3941 if "<message" in line or "<!--" in line or "-->" in line:
3942 continue
3943 if test_case["incorrect_name"] in line:
3944 problems.append(
3945 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3946
3947 if problems:
3948 message = (
3949 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3950 % (test_case["correct_name"], test_case["correct_name"],
3951 test_case["incorrect_name"]))
3952 all_problems.append(
3953 output_api.PresubmitPromptWarning(message, items=problems))
3954
3955 return all_problems
3956
3957
Dirk Pranke3c18a382019-03-15 01:07:513958def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3959 # TODO(crbug.com/941824): We need to make sure the entries in
3960 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3961 # so that users of //buildtools in other projects get the same tooling
3962 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3963 # support to gclient, we can eliminate the duplication and delete
3964 # this presubmit check.
3965
3966 # Update this regexp if new revisions are added to the files.
3967 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013968 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513969
3970 # If a user is changing one revision, they need to change the same
3971 # line in both files. This means that any given change should contain
3972 # exactly the same list of changed lines that match the regexps. The
3973 # replace(' ', '') call allows us to ignore whitespace changes to the
3974 # lines. The 'long_text' parameter to the error will contain the
3975 # list of changed lines in both files, which should make it easy enough
3976 # to spot the error without going overboard in this implementation.
3977 revs_changes = {
3978 'DEPS': {},
3979 'buildtools/DEPS': {},
3980 }
3981 long_text = ''
3982
3983 for f in input_api.AffectedFiles(
3984 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3985 for line_num, line in f.ChangedContents():
3986 if rev_regexp.search(line):
3987 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3988 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3989
3990 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3991 return [output_api.PresubmitError(
3992 'Change buildtools revisions in sync in both //DEPS and '
3993 '//buildtools/DEPS.', long_text=long_text + '\n')]
3994 else:
3995 return []
3996
3997
Daniel Bratell93eb6c62019-04-29 20:13:363998def _CheckForTooLargeFiles(input_api, output_api):
3999 """Avoid large files, especially binary files, in the repository since
4000 git doesn't scale well for those. They will be in everyone's repo
4001 clones forever, forever making Chromium slower to clone and work
4002 with."""
4003
4004 # Uploading files to cloud storage is not trivial so we don't want
4005 # to set the limit too low, but the upper limit for "normal" large
4006 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4007 # anything over 20 MB is exceptional.
4008 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4009
4010 too_large_files = []
4011 for f in input_api.AffectedFiles():
4012 # Check both added and modified files (but not deleted files).
4013 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384014 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364015 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4016 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4017
4018 if too_large_files:
4019 message = (
4020 'Do not commit large files to git since git scales badly for those.\n' +
4021 'Instead put the large files in cloud storage and use DEPS to\n' +
4022 'fetch them.\n' + '\n'.join(too_large_files)
4023 )
4024 return [output_api.PresubmitError(
4025 'Too large files found in commit', long_text=message + '\n')]
4026 else:
4027 return []
4028
Max Morozb47503b2019-08-08 21:03:274029
4030def _CheckFuzzTargets(input_api, output_api):
4031 """Checks specific for fuzz target sources."""
4032 EXPORTED_SYMBOLS = [
4033 'LLVMFuzzerInitialize',
4034 'LLVMFuzzerCustomMutator',
4035 'LLVMFuzzerCustomCrossOver',
4036 'LLVMFuzzerMutate',
4037 ]
4038
4039 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4040
4041 def FilterFile(affected_file):
4042 """Ignore libFuzzer source code."""
4043 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4044 black_list = r"^third_party[\\/]libFuzzer"
4045
4046 return input_api.FilterSourceFile(
4047 affected_file,
4048 white_list=[white_list],
4049 black_list=[black_list])
4050
4051 files_with_missing_header = []
4052 for f in input_api.AffectedSourceFiles(FilterFile):
4053 contents = input_api.ReadFile(f, 'r')
4054 if REQUIRED_HEADER in contents:
4055 continue
4056
4057 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4058 files_with_missing_header.append(f.LocalPath())
4059
4060 if not files_with_missing_header:
4061 return []
4062
4063 long_text = (
4064 'If you define any of the libFuzzer optional functions (%s), it is '
4065 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4066 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4067 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4068 'to access command line arguments passed to the fuzzer. Instead, prefer '
4069 'static initialization and shared resources as documented in '
4070 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4071 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4072 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4073 )
4074
4075 return [output_api.PresubmitPromptWarning(
4076 message="Missing '%s' in:" % REQUIRED_HEADER,
4077 items=files_with_missing_header,
4078 long_text=long_text)]
4079
4080
Mohamed Heikald048240a2019-11-12 16:57:374081def _CheckNewImagesWarning(input_api, output_api):
4082 """
4083 Warns authors who add images into the repo to make sure their images are
4084 optimized before committing.
4085 """
4086 images_added = False
4087 image_paths = []
4088 errors = []
4089 filter_lambda = lambda x: input_api.FilterSourceFile(
4090 x,
4091 black_list=(('(?i).*test', r'.*\/junit\/')
4092 + input_api.DEFAULT_BLACK_LIST),
4093 white_list=[r'.*\/(drawable|mipmap)' ]
4094 )
4095 for f in input_api.AffectedFiles(
4096 include_deletes=False, file_filter=filter_lambda):
4097 local_path = f.LocalPath().lower()
4098 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4099 images_added = True
4100 image_paths.append(f)
4101 if images_added:
4102 errors.append(output_api.PresubmitPromptWarning(
4103 'It looks like you are trying to commit some images. If these are '
4104 'non-test-only images, please make sure to read and apply the tips in '
4105 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4106 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4107 'FYI only and will not block your CL on the CQ.', image_paths))
4108 return errors
4109
4110
dgnaa68d5e2015-06-10 10:08:224111def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574112 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224113 results = []
dgnaa68d5e2015-06-10 10:08:224114 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174115 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224116 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294117 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064118 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4119 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424120 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184121 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574122 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374123 results.extend(_CheckNewImagesWarning(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574124 return results
4125
4126def _AndroidSpecificOnCommitChecks(input_api, output_api):
4127 """Groups commit checks that target android code."""
4128 results = []
4129 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224130 return results
4131
4132
[email protected]22c9bd72011-03-27 16:47:394133def _CommonChecks(input_api, output_api):
4134 """Checks common to both upload and commit."""
4135 results = []
4136 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384137 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544138 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084139
4140 author = input_api.change.author_email
4141 if author and author not in _KNOWN_ROBOTS:
4142 results.extend(
4143 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4144
[email protected]55459852011-08-10 15:17:194145 results.extend(
[email protected]760deea2013-12-10 19:33:494146 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234147 results.extend(
4148 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544149 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184150 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344151 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524152 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224153 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444154 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594155 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314156 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064157 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124158 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184159 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224160 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304161 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494162 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034163 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494164 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444165 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294166 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274167 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074168 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544169 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444170 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394171 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554172 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044173 results.extend(
4174 input_api.canned_checks.CheckChangeHasNoTabs(
4175 input_api,
4176 output_api,
4177 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404178 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164179 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084180 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244181 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474182 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044183 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054184 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144185 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234186 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434187 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404188 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154189 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174190 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264191 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504192 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364193 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064194 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134195 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434196 results.extend(input_api.RunTests(
4197 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144198 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024199 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514200 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364201 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004202 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244203
Vaclav Brozekcdc7defb2018-03-20 09:54:354204 for f in input_api.AffectedFiles():
4205 path, name = input_api.os_path.split(f.LocalPath())
4206 if name == 'PRESUBMIT.py':
4207 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004208 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4209 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074210 # The PRESUBMIT.py file (and the directory containing it) might
4211 # have been affected by being moved or removed, so only try to
4212 # run the tests if they still exist.
4213 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4214 input_api, output_api, full_path,
4215 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394216 return results
[email protected]1f7b4172010-01-28 01:17:344217
[email protected]b337cb5b2011-01-23 21:24:054218
[email protected]b8079ae4a2012-12-05 19:56:494219def _CheckPatchFiles(input_api, output_api):
4220 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4221 if f.LocalPath().endswith(('.orig', '.rej'))]
4222 if problems:
4223 return [output_api.PresubmitError(
4224 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034225 else:
4226 return []
[email protected]b8079ae4a2012-12-05 19:56:494227
4228
Kent Tamura5a8755d2017-06-29 23:37:074229def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214230 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4231 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4232 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074233 include_re = input_api.re.compile(
4234 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4235 extension_re = input_api.re.compile(r'\.[a-z]+$')
4236 errors = []
4237 for f in input_api.AffectedFiles():
4238 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4239 continue
4240 found_line_number = None
4241 found_macro = None
4242 for line_num, line in f.ChangedContents():
4243 match = macro_re.search(line)
4244 if match:
4245 found_line_number = line_num
4246 found_macro = match.group(2)
4247 break
4248 if not found_line_number:
4249 continue
4250
4251 found_include = False
4252 for line in f.NewContents():
4253 if include_re.search(line):
4254 found_include = True
4255 break
4256 if found_include:
4257 continue
4258
4259 if not f.LocalPath().endswith('.h'):
4260 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4261 try:
4262 content = input_api.ReadFile(primary_header_path, 'r')
4263 if include_re.search(content):
4264 continue
4265 except IOError:
4266 pass
4267 errors.append('%s:%d %s macro is used without including build/'
4268 'build_config.h.'
4269 % (f.LocalPath(), found_line_number, found_macro))
4270 if errors:
4271 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4272 return []
4273
4274
[email protected]b00342e7f2013-03-26 16:21:544275def _DidYouMeanOSMacro(bad_macro):
4276 try:
4277 return {'A': 'OS_ANDROID',
4278 'B': 'OS_BSD',
4279 'C': 'OS_CHROMEOS',
4280 'F': 'OS_FREEBSD',
4281 'L': 'OS_LINUX',
4282 'M': 'OS_MACOSX',
4283 'N': 'OS_NACL',
4284 'O': 'OS_OPENBSD',
4285 'P': 'OS_POSIX',
4286 'S': 'OS_SOLARIS',
4287 'W': 'OS_WIN'}[bad_macro[3].upper()]
4288 except KeyError:
4289 return ''
4290
4291
4292def _CheckForInvalidOSMacrosInFile(input_api, f):
4293 """Check for sensible looking, totally invalid OS macros."""
4294 preprocessor_statement = input_api.re.compile(r'^\s*#')
4295 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4296 results = []
4297 for lnum, line in f.ChangedContents():
4298 if preprocessor_statement.search(line):
4299 for match in os_macro.finditer(line):
4300 if not match.group(1) in _VALID_OS_MACROS:
4301 good = _DidYouMeanOSMacro(match.group(1))
4302 did_you_mean = ' (did you mean %s?)' % good if good else ''
4303 results.append(' %s:%d %s%s' % (f.LocalPath(),
4304 lnum,
4305 match.group(1),
4306 did_you_mean))
4307 return results
4308
4309
4310def _CheckForInvalidOSMacros(input_api, output_api):
4311 """Check all affected files for invalid OS macros."""
4312 bad_macros = []
tzik3f295992018-12-04 20:32:234313 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474314 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544315 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4316
4317 if not bad_macros:
4318 return []
4319
4320 return [output_api.PresubmitError(
4321 'Possibly invalid OS macro[s] found. Please fix your code\n'
4322 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4323
lliabraa35bab3932014-10-01 12:16:444324
4325def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4326 """Check all affected files for invalid "if defined" macros."""
4327 ALWAYS_DEFINED_MACROS = (
4328 "TARGET_CPU_PPC",
4329 "TARGET_CPU_PPC64",
4330 "TARGET_CPU_68K",
4331 "TARGET_CPU_X86",
4332 "TARGET_CPU_ARM",
4333 "TARGET_CPU_MIPS",
4334 "TARGET_CPU_SPARC",
4335 "TARGET_CPU_ALPHA",
4336 "TARGET_IPHONE_SIMULATOR",
4337 "TARGET_OS_EMBEDDED",
4338 "TARGET_OS_IPHONE",
4339 "TARGET_OS_MAC",
4340 "TARGET_OS_UNIX",
4341 "TARGET_OS_WIN32",
4342 )
4343 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4344 results = []
4345 for lnum, line in f.ChangedContents():
4346 for match in ifdef_macro.finditer(line):
4347 if match.group(1) in ALWAYS_DEFINED_MACROS:
4348 always_defined = ' %s is always defined. ' % match.group(1)
4349 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4350 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4351 lnum,
4352 always_defined,
4353 did_you_mean))
4354 return results
4355
4356
4357def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4358 """Check all affected files for invalid "if defined" macros."""
4359 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054360 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444361 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054362 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214363 continue
lliabraa35bab3932014-10-01 12:16:444364 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4365 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4366
4367 if not bad_macros:
4368 return []
4369
4370 return [output_api.PresubmitError(
4371 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4372 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4373 bad_macros)]
4374
4375
mlamouria82272622014-09-16 18:45:044376def _CheckForIPCRules(input_api, output_api):
4377 """Check for same IPC rules described in
4378 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4379 """
4380 base_pattern = r'IPC_ENUM_TRAITS\('
4381 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4382 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4383
4384 problems = []
4385 for f in input_api.AffectedSourceFiles(None):
4386 local_path = f.LocalPath()
4387 if not local_path.endswith('.h'):
4388 continue
4389 for line_number, line in f.ChangedContents():
4390 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4391 problems.append(
4392 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4393
4394 if problems:
4395 return [output_api.PresubmitPromptWarning(
4396 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4397 else:
4398 return []
4399
[email protected]b00342e7f2013-03-26 16:21:544400
Stephen Martinis97a394142018-06-07 23:06:054401def _CheckForLongPathnames(input_api, output_api):
4402 """Check to make sure no files being submitted have long paths.
4403 This causes issues on Windows.
4404 """
4405 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194406 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054407 local_path = f.LocalPath()
4408 # Windows has a path limit of 260 characters. Limit path length to 200 so
4409 # that we have some extra for the prefix on dev machines and the bots.
4410 if len(local_path) > 200:
4411 problems.append(local_path)
4412
4413 if problems:
4414 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4415 else:
4416 return []
4417
4418
Daniel Bratell8ba52722018-03-02 16:06:144419def _CheckForIncludeGuards(input_api, output_api):
4420 """Check that header files have proper guards against multiple inclusion.
4421 If a file should not have such guards (and it probably should) then it
4422 should include the string "no-include-guard-because-multiply-included".
4423 """
Daniel Bratell6a75baef62018-06-04 10:04:454424 def is_chromium_header_file(f):
4425 # We only check header files under the control of the Chromium
4426 # project. That is, those outside third_party apart from
4427 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324428 # We also exclude *_message_generator.h headers as they use
4429 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454430 file_with_path = input_api.os_path.normpath(f.LocalPath())
4431 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324432 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454433 (not file_with_path.startswith('third_party') or
4434 file_with_path.startswith(
4435 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144436
4437 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344438 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144439
4440 errors = []
4441
Daniel Bratell6a75baef62018-06-04 10:04:454442 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144443 guard_name = None
4444 guard_line_number = None
4445 seen_guard_end = False
4446
4447 file_with_path = input_api.os_path.normpath(f.LocalPath())
4448 base_file_name = input_api.os_path.splitext(
4449 input_api.os_path.basename(file_with_path))[0]
4450 upper_base_file_name = base_file_name.upper()
4451
4452 expected_guard = replace_special_with_underscore(
4453 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144454
4455 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574456 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4457 # are too many (1000+) files with slight deviations from the
4458 # coding style. The most important part is that the include guard
4459 # is there, and that it's unique, not the name so this check is
4460 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144461 #
4462 # As code becomes more uniform, this could be made stricter.
4463
4464 guard_name_pattern_list = [
4465 # Anything with the right suffix (maybe with an extra _).
4466 r'\w+_H__?',
4467
Daniel Bratell39b5b062018-05-16 18:09:574468 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144469 r'\w+_h',
4470
4471 # Anything including the uppercase name of the file.
4472 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4473 upper_base_file_name)) + r'\w*',
4474 ]
4475 guard_name_pattern = '|'.join(guard_name_pattern_list)
4476 guard_pattern = input_api.re.compile(
4477 r'#ifndef\s+(' + guard_name_pattern + ')')
4478
4479 for line_number, line in enumerate(f.NewContents()):
4480 if 'no-include-guard-because-multiply-included' in line:
4481 guard_name = 'DUMMY' # To not trigger check outside the loop.
4482 break
4483
4484 if guard_name is None:
4485 match = guard_pattern.match(line)
4486 if match:
4487 guard_name = match.group(1)
4488 guard_line_number = line_number
4489
Daniel Bratell39b5b062018-05-16 18:09:574490 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454491 # don't match the chromium style guide, but new files should
4492 # get it right.
4493 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574494 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144495 errors.append(output_api.PresubmitPromptWarning(
4496 'Header using the wrong include guard name %s' % guard_name,
4497 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574498 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144499 else:
4500 # The line after #ifndef should have a #define of the same name.
4501 if line_number == guard_line_number + 1:
4502 expected_line = '#define %s' % guard_name
4503 if line != expected_line:
4504 errors.append(output_api.PresubmitPromptWarning(
4505 'Missing "%s" for include guard' % expected_line,
4506 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4507 'Expected: %r\nGot: %r' % (expected_line, line)))
4508
4509 if not seen_guard_end and line == '#endif // %s' % guard_name:
4510 seen_guard_end = True
4511 elif seen_guard_end:
4512 if line.strip() != '':
4513 errors.append(output_api.PresubmitPromptWarning(
4514 'Include guard %s not covering the whole file' % (
4515 guard_name), [f.LocalPath()]))
4516 break # Nothing else to check and enough to warn once.
4517
4518 if guard_name is None:
4519 errors.append(output_api.PresubmitPromptWarning(
4520 'Missing include guard %s' % expected_guard,
4521 [f.LocalPath()],
4522 'Missing include guard in %s\n'
4523 'Recommended name: %s\n'
4524 'This check can be disabled by having the string\n'
4525 'no-include-guard-because-multiply-included in the header.' %
4526 (f.LocalPath(), expected_guard)))
4527
4528 return errors
4529
4530
mostynbb639aca52015-01-07 20:31:234531def _CheckForWindowsLineEndings(input_api, output_api):
4532 """Check source code and known ascii text files for Windows style line
4533 endings.
4534 """
earthdok1b5e0ee2015-03-10 15:19:104535 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234536
4537 file_inclusion_pattern = (
4538 known_text_files,
4539 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4540 )
4541
mostynbb639aca52015-01-07 20:31:234542 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534543 source_file_filter = lambda f: input_api.FilterSourceFile(
4544 f, white_list=file_inclusion_pattern, black_list=None)
4545 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504546 include_file = False
4547 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234548 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504549 include_file = True
4550 if include_file:
4551 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234552
4553 if problems:
4554 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4555 'these files to contain Windows style line endings?\n' +
4556 '\n'.join(problems))]
4557
4558 return []
4559
4560
Vaclav Brozekd5de76a2018-03-17 07:57:504561def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134562 """Checks that all source files use SYSLOG properly."""
4563 syslog_files = []
4564 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564565 for line_number, line in f.ChangedContents():
4566 if 'SYSLOG' in line:
4567 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4568
pastarmovj89f7ee12016-09-20 14:58:134569 if syslog_files:
4570 return [output_api.PresubmitPromptWarning(
4571 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4572 ' calls.\nFiles to check:\n', items=syslog_files)]
4573 return []
4574
4575
[email protected]1f7b4172010-01-28 01:17:344576def CheckChangeOnUpload(input_api, output_api):
4577 results = []
4578 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474579 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284580 results.extend(
jam93a6ee792017-02-08 23:59:224581 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194582 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224583 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134584 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164585 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534586 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194587 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274588 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544589 return results
[email protected]ca8d1982009-02-19 16:33:124590
4591
[email protected]1bfb8322014-04-23 01:02:414592def GetTryServerMasterForBot(bot):
4593 """Returns the Try Server master for the given bot.
4594
[email protected]0bb112362014-07-26 04:38:324595 It tries to guess the master from the bot name, but may still fail
4596 and return None. There is no longer a default master.
4597 """
4598 # Potentially ambiguous bot names are listed explicitly.
4599 master_map = {
tandriie5587792016-07-14 00:34:504600 'chromium_presubmit': 'master.tryserver.chromium.linux',
4601 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414602 }
[email protected]0bb112362014-07-26 04:38:324603 master = master_map.get(bot)
4604 if not master:
wnwen4fbaab82016-05-25 12:54:364605 if 'android' in bot:
tandriie5587792016-07-14 00:34:504606 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364607 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504608 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324609 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504610 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324611 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504612 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324613 return master
[email protected]1bfb8322014-04-23 01:02:414614
4615
[email protected]ca8d1982009-02-19 16:33:124616def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544617 results = []
[email protected]1f7b4172010-01-28 01:17:344618 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574619 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544620 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274621 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344622 input_api,
4623 output_api,
[email protected]2fdd1f362013-01-16 03:56:034624 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274625
jam93a6ee792017-02-08 23:59:224626 results.extend(
4627 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544628 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4629 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384630 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4631 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414632 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4633 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544634 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144635
4636
4637def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144638 import os
4639 import sys
4640 from io import StringIO
4641
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144642 new_or_added_paths = set(f.LocalPath()
4643 for f in input_api.AffectedFiles()
4644 if (f.Action() == 'A' or f.Action() == 'M'))
4645 removed_paths = set(f.LocalPath()
4646 for f in input_api.AffectedFiles(include_deletes=True)
4647 if f.Action() == 'D')
4648
4649 affected_grds = [f for f in input_api.AffectedFiles()
4650 if (f.LocalPath().endswith('.grd') or
4651 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164652 if not affected_grds:
4653 return []
4654
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144655 affected_png_paths = [f.AbsoluteLocalPath()
4656 for f in input_api.AffectedFiles()
4657 if (f.LocalPath().endswith('.png'))]
4658
4659 # Check for screenshots. Developers can upload screenshots using
4660 # tools/translation/upload_screenshots.py which finds and uploads
4661 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4662 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4663 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4664 #
4665 # The logic here is as follows:
4666 #
4667 # - If the CL has a .png file under the screenshots directory for a grd
4668 # file, warn the developer. Actual images should never be checked into the
4669 # Chrome repo.
4670 #
4671 # - If the CL contains modified or new messages in grd files and doesn't
4672 # contain the corresponding .sha1 files, warn the developer to add images
4673 # and upload them via tools/translation/upload_screenshots.py.
4674 #
4675 # - If the CL contains modified or new messages in grd files and the
4676 # corresponding .sha1 files, everything looks good.
4677 #
4678 # - If the CL contains removed messages in grd files but the corresponding
4679 # .sha1 files aren't removed, warn the developer to remove them.
4680 unnecessary_screenshots = []
4681 missing_sha1 = []
4682 unnecessary_sha1_files = []
4683
4684
4685 def _CheckScreenshotAdded(screenshots_dir, message_id):
4686 sha1_path = input_api.os_path.join(
4687 screenshots_dir, message_id + '.png.sha1')
4688 if sha1_path not in new_or_added_paths:
4689 missing_sha1.append(sha1_path)
4690
4691
4692 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4693 sha1_path = input_api.os_path.join(
4694 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034695 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144696 unnecessary_sha1_files.append(sha1_path)
4697
meacer8c0d3832019-12-26 21:46:164698 try:
4699 old_sys_path = sys.path
4700 sys.path = sys.path + [input_api.os_path.join(
4701 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4702 from helper import grd_helper
4703 finally:
4704 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144705
4706 for f in affected_grds:
4707 file_path = f.LocalPath()
4708 old_id_to_msg_map = {}
4709 new_id_to_msg_map = {}
4710 if file_path.endswith('.grdp'):
4711 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584712 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394713 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144714 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584715 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394716 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144717 else:
meacerff8a9b62019-12-10 19:43:584718 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144719 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584720 old_id_to_msg_map = grd_helper.GetGrdMessages(
4721 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144722 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584723 new_id_to_msg_map = grd_helper.GetGrdMessages(
4724 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144725
4726 # Compute added, removed and modified message IDs.
4727 old_ids = set(old_id_to_msg_map)
4728 new_ids = set(new_id_to_msg_map)
4729 added_ids = new_ids - old_ids
4730 removed_ids = old_ids - new_ids
4731 modified_ids = set([])
4732 for key in old_ids.intersection(new_ids):
4733 if (old_id_to_msg_map[key].FormatXml()
4734 != new_id_to_msg_map[key].FormatXml()):
4735 modified_ids.add(key)
4736
4737 grd_name, ext = input_api.os_path.splitext(
4738 input_api.os_path.basename(file_path))
4739 screenshots_dir = input_api.os_path.join(
4740 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4741
4742 # Check the screenshot directory for .png files. Warn if there is any.
4743 for png_path in affected_png_paths:
4744 if png_path.startswith(screenshots_dir):
4745 unnecessary_screenshots.append(png_path)
4746
4747 for added_id in added_ids:
4748 _CheckScreenshotAdded(screenshots_dir, added_id)
4749
4750 for modified_id in modified_ids:
4751 _CheckScreenshotAdded(screenshots_dir, modified_id)
4752
4753 for removed_id in removed_ids:
4754 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4755
4756 results = []
4757 if unnecessary_screenshots:
4758 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394759 'Do not include actual screenshots in the changelist. Run '
4760 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144761 sorted(unnecessary_screenshots)))
4762
4763 if missing_sha1:
4764 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394765 'You are adding or modifying UI strings.\n'
4766 'To ensure the best translations, take screenshots of the relevant UI '
4767 '(https://g.co/chrome/translation) and add these files to your '
4768 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144769
4770 if unnecessary_sha1_files:
4771 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394772 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144773 sorted(unnecessary_sha1_files)))
4774
4775 return results