blob: dc3c2af79c6e4859caeceab8b4ca02ba5ec93aec [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
Michael Thiessen44457642020-02-06 00:24:1582# Format: Sequence of tuples containing:
83# * Full import path.
84# * Sequence of strings to show when the pattern matches.
85# * Sequence of path or filename exceptions to this rule
86_BANNED_JAVA_IMPORTS = (
87 (
88 'java.net.URI',
89 (
90 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
91 ),
92 (
93 'net/android/javatests/src/org/chromium/net/'
94 'AndroidProxySelectorTest.java',
95 'components/cronet/',
96 ),
97 ),
98)
wnwenbdc444e2016-05-25 13:44:1599
Daniel Bratell609102be2019-03-27 20:53:21100# Format: Sequence of tuples containing:
101# * String pattern or, if starting with a slash, a regular expression.
102# * Sequence of strings to show when the pattern matches.
103# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:41104_BANNED_JAVA_FUNCTIONS = (
105 (
106 'StrictMode.allowThreadDiskReads()',
107 (
108 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
109 'directly.',
110 ),
111 False,
112 ),
113 (
114 'StrictMode.allowThreadDiskWrites()',
115 (
116 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
117 'directly.',
118 ),
119 False,
120 ),
121)
122
Daniel Bratell609102be2019-03-27 20:53:21123# Format: Sequence of tuples containing:
124# * String pattern or, if starting with a slash, a regular expression.
125# * Sequence of strings to show when the pattern matches.
126# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59127_BANNED_OBJC_FUNCTIONS = (
128 (
129 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59132 'prohibited. Please use CrTrackingArea instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 False,
136 ),
137 (
[email protected]eaae1972014-04-16 04:17:26138 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20139 (
140 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59141 'instead.',
142 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
143 ),
144 False,
145 ),
146 (
147 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20148 (
149 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59150 'Please use |convertPoint:(point) fromView:nil| instead.',
151 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
152 ),
153 True,
154 ),
155 (
156 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59159 'Please use |convertPoint:(point) toView:nil| instead.',
160 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
161 ),
162 True,
163 ),
164 (
165 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59168 'Please use |convertRect:(point) fromView:nil| instead.',
169 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
170 ),
171 True,
172 ),
173 (
174 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20175 (
176 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59177 'Please use |convertRect:(point) toView:nil| instead.',
178 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
179 ),
180 True,
181 ),
182 (
183 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20184 (
185 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59186 'Please use |convertSize:(point) fromView:nil| instead.',
187 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
188 ),
189 True,
190 ),
191 (
192 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20193 (
194 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59195 'Please use |convertSize:(point) toView:nil| instead.',
196 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
197 ),
198 True,
199 ),
jif65398702016-10-27 10:19:48200 (
201 r"/\s+UTF8String\s*]",
202 (
203 'The use of -[NSString UTF8String] is dangerous as it can return null',
204 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
205 'Please use |SysNSStringToUTF8| instead.',
206 ),
207 True,
208 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34209 (
210 r'__unsafe_unretained',
211 (
212 'The use of __unsafe_unretained is almost certainly wrong, unless',
213 'when interacting with NSFastEnumeration or NSInvocation.',
214 'Please use __weak in files build with ARC, nothing otherwise.',
215 ),
216 False,
217 ),
Avi Drissman7382afa02019-04-29 23:27:13218 (
219 'freeWhenDone:NO',
220 (
221 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
222 'Foundation types is prohibited.',
223 ),
224 True,
225 ),
[email protected]127f18ec2012-06-16 05:05:59226)
227
Daniel Bratell609102be2019-03-27 20:53:21228# Format: Sequence of tuples containing:
229# * String pattern or, if starting with a slash, a regular expression.
230# * Sequence of strings to show when the pattern matches.
231# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54232_BANNED_IOS_OBJC_FUNCTIONS = (
233 (
234 r'/\bTEST[(]',
235 (
236 'TEST() macro should not be used in Objective-C++ code as it does not ',
237 'drain the autorelease pool at the end of the test. Use TEST_F() ',
238 'macro instead with a fixture inheriting from PlatformTest (or a ',
239 'typedef).'
240 ),
241 True,
242 ),
243 (
244 r'/\btesting::Test\b',
245 (
246 'testing::Test should not be used in Objective-C++ code as it does ',
247 'not drain the autorelease pool at the end of the test. Use ',
248 'PlatformTest instead.'
249 ),
250 True,
251 ),
252)
253
Peter K. Lee6c03ccff2019-07-15 14:40:05254# Format: Sequence of tuples containing:
255# * String pattern or, if starting with a slash, a regular expression.
256# * Sequence of strings to show when the pattern matches.
257# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
258_BANNED_IOS_EGTEST_FUNCTIONS = (
259 (
260 r'/\bEXPECT_OCMOCK_VERIFY\b',
261 (
262 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
263 'it is meant for GTests. Use [mock verify] instead.'
264 ),
265 True,
266 ),
267)
268
danakj7a2b7082019-05-21 21:13:51269# Directories that contain deprecated Bind() or Callback types.
270# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36271# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51272# echo "-- $i"
danakj710b4c02019-11-28 16:08:45273# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51274# done
275#
276# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
277# when they have been converted to modern callback types (OnceCallback,
278# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
279# checks for them and prevent regressions.
280_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
danakj7a2b7082019-05-21 21:13:51281 '^apps/',
danakj7a2b7082019-05-21 21:13:51282 '^base/callback.h', # Intentional.
283 '^chrome/app/',
284 '^chrome/browser/',
285 '^chrome/chrome_elf/',
danakj7a2b7082019-05-21 21:13:51286 '^chrome/common/',
287 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51288 '^chrome/renderer/',
289 '^chrome/services/',
290 '^chrome/test/',
291 '^chrome/tools/',
292 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51293 '^chromecast/media/',
294 '^chromecast/metrics/',
295 '^chromecast/net/',
296 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51297 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51298 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51299 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51300 '^components/arc/',
301 '^components/assist_ranker/',
302 '^components/autofill/',
303 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51304 '^components/browser_watcher/',
danakj7a2b7082019-05-21 21:13:51305 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51306 '^components/chromeos_camera/',
307 '^components/component_updater/',
308 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51309 '^components/cronet/',
310 '^components/data_reduction_proxy/',
danakj7a2b7082019-05-21 21:13:51311 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36312 '^components/dom_distiller/',
danakj7a2b7082019-05-21 21:13:51313 '^components/download/',
314 '^components/drive/',
315 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51316 '^components/feature_engagement/',
317 '^components/feedback/',
318 '^components/flags_ui/',
319 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51320 '^components/guest_view/',
321 '^components/heap_profiling/',
322 '^components/history/',
323 '^components/image_fetcher/',
324 '^components/invalidation/',
325 '^components/keyed_service/',
326 '^components/login/',
327 '^components/metrics/',
328 '^components/metrics_services_manager/',
329 '^components/nacl/',
330 '^components/navigation_interception/',
331 '^components/net_log/',
332 '^components/network_time/',
333 '^components/ntp_snippets/',
334 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51335 '^components/offline_pages/',
336 '^components/omnibox/',
337 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51338 '^components/password_manager/',
339 '^components/payments/',
340 '^components/plugins/',
341 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51342 '^components/proxy_config/',
343 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51344 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51345 '^components/rlz/',
346 '^components/safe_browsing/',
347 '^components/search_engines/',
348 '^components/search_provider_logos/',
349 '^components/security_interstitials/',
350 '^components/security_state/',
351 '^components/services/',
352 '^components/sessions/',
353 '^components/signin/',
354 '^components/ssl_errors/',
355 '^components/storage_monitor/',
356 '^components/subresource_filter/',
357 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51358 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51359 '^components/sync_preferences/',
360 '^components/sync_sessions/',
361 '^components/test/',
362 '^components/tracing/',
363 '^components/translate/',
364 '^components/ukm/',
365 '^components/update_client/',
366 '^components/upload_list/',
367 '^components/variations/',
368 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51369 '^components/webcrypto/',
370 '^components/webdata/',
371 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51372 '^device/bluetooth/',
danakj7a2b7082019-05-21 21:13:51373 '^extensions/',
danakj7a2b7082019-05-21 21:13:51374 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51375 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51376 '^ios/chrome/',
377 '^ios/components/',
378 '^ios/net/',
379 '^ios/web/',
380 '^ios/web_view/',
381 '^ipc/',
382 '^media/audio/',
383 '^media/base/',
danakjc8576092019-11-26 19:01:36384 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51385 '^media/capture/',
386 '^media/cast/',
387 '^media/cdm/',
388 '^media/device_monitors/',
389 '^media/ffmpeg/',
390 '^media/filters/',
391 '^media/formats/',
392 '^media/gpu/',
393 '^media/mojo/',
394 '^media/muxers/',
395 '^media/remoting/',
396 '^media/renderers/',
397 '^media/test/',
danakj7a2b7082019-05-21 21:13:51398 '^net/',
399 '^ppapi/proxy/',
400 '^ppapi/shared_impl/',
401 '^ppapi/tests/',
402 '^ppapi/thunk/',
403 '^remoting/base/',
404 '^remoting/client/',
danakj7a2b7082019-05-21 21:13:51405 '^remoting/host/',
406 '^remoting/internal/',
danakj7a2b7082019-05-21 21:13:51407 '^remoting/protocol/',
danakj7a2b7082019-05-21 21:13:51408 '^services/',
danakj7a2b7082019-05-21 21:13:51409 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51410 '^tools/clang/base_bind_rewriters/', # Intentional.
411 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51412))
[email protected]127f18ec2012-06-16 05:05:59413
Daniel Bratell609102be2019-03-27 20:53:21414# Format: Sequence of tuples containing:
415# * String pattern or, if starting with a slash, a regular expression.
416# * Sequence of strings to show when the pattern matches.
417# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
418# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59419_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20420 (
Dave Tapuska98199b612019-07-10 13:30:44421 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53422 (
423 'New code should not use NULL. Use nullptr instead.',
424 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20425 False,
thomasandersone7caaa9b2017-03-29 19:22:53426 (),
427 ),
Peter Kasting94a56c42019-10-25 21:54:04428 (
429 r'/\busing namespace ',
430 (
431 'Using directives ("using namespace x") are banned by the Google Style',
432 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
433 'Explicitly qualify symbols or use using declarations ("using x::foo").',
434 ),
435 True,
436 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
437 ),
Antonio Gomes07300d02019-03-13 20:59:57438 # Make sure that gtest's FRIEND_TEST() macro is not used; the
439 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
440 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53441 (
[email protected]23e6cbc2012-06-16 18:51:20442 'FRIEND_TEST(',
443 (
[email protected]e3c945502012-06-26 20:01:49444 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20445 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
446 ),
447 False,
[email protected]7345da02012-11-27 14:31:49448 (),
[email protected]23e6cbc2012-06-16 18:51:20449 ),
450 (
Dave Tapuska98199b612019-07-10 13:30:44451 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53452 (
453 'Chrome clients wishing to select events on X windows should use',
454 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
455 'you are selecting events from the GPU process, or if you are using',
456 'an XDisplay other than gfx::GetXDisplay().',
457 ),
458 True,
459 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40460 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04461 r"^ui[\\/]gl[\\/].*\.cc$",
462 r"^media[\\/]gpu[\\/].*\.cc$",
463 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53464 ),
465 ),
466 (
Dave Tapuska98199b612019-07-10 13:30:44467 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20468 (
thomasanderson11aa41d2017-06-08 22:22:38469 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20470 ),
471 True,
472 (
Egor Paskoce145c42018-09-28 19:31:04473 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
474 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
475 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20476 ),
477 ),
478 (
tomhudsone2c14d552016-05-26 17:07:46479 'setMatrixClip',
480 (
481 'Overriding setMatrixClip() is prohibited; ',
482 'the base function is deprecated. ',
483 ),
484 True,
485 (),
486 ),
487 (
[email protected]52657f62013-05-20 05:30:31488 'SkRefPtr',
489 (
490 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22491 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31492 ),
493 True,
494 (),
495 ),
496 (
497 'SkAutoRef',
498 (
499 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22500 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31501 ),
502 True,
503 (),
504 ),
505 (
506 'SkAutoTUnref',
507 (
508 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22509 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31510 ),
511 True,
512 (),
513 ),
514 (
515 'SkAutoUnref',
516 (
517 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
518 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22519 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31520 ),
521 True,
522 (),
523 ),
[email protected]d89eec82013-12-03 14:10:59524 (
525 r'/HANDLE_EINTR\(.*close',
526 (
527 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
528 'descriptor will be closed, and it is incorrect to retry the close.',
529 'Either call close directly and ignore its return value, or wrap close',
530 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
531 ),
532 True,
533 (),
534 ),
535 (
536 r'/IGNORE_EINTR\((?!.*close)',
537 (
538 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
539 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
540 ),
541 True,
542 (
543 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04544 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
545 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59546 ),
547 ),
[email protected]ec5b3f02014-04-04 18:43:43548 (
549 r'/v8::Extension\(',
550 (
551 'Do not introduce new v8::Extensions into the code base, use',
552 'gin::Wrappable instead. See http://crbug.com/334679',
553 ),
554 True,
[email protected]f55c90ee62014-04-12 00:50:03555 (
Egor Paskoce145c42018-09-28 19:31:04556 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03557 ),
[email protected]ec5b3f02014-04-04 18:43:43558 ),
skyostilf9469f72015-04-20 10:38:52559 (
jame2d1a952016-04-02 00:27:10560 '#pragma comment(lib,',
561 (
562 'Specify libraries to link with in build files and not in the source.',
563 ),
564 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41565 (
tzik3f295992018-12-04 20:32:23566 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04567 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41568 ),
jame2d1a952016-04-02 00:27:10569 ),
fdorayc4ac18d2017-05-01 21:39:59570 (
Gabriel Charette7cc6c432018-04-25 20:52:02571 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59572 (
573 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
574 ),
575 False,
576 (),
577 ),
578 (
Gabriel Charette7cc6c432018-04-25 20:52:02579 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59580 (
581 'Consider using THREAD_CHECKER macros instead of the class directly.',
582 ),
583 False,
584 (),
585 ),
dbeamb6f4fde2017-06-15 04:03:06586 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06587 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
588 (
589 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
590 'deprecated (http://crbug.com/634507). Please avoid converting away',
591 'from the Time types in Chromium code, especially if any math is',
592 'being done on time values. For interfacing with platform/library',
593 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
594 'type converter methods instead. For faking TimeXXX values (for unit',
595 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
596 'other use cases, please contact base/time/OWNERS.',
597 ),
598 False,
599 (),
600 ),
601 (
dbeamb6f4fde2017-06-15 04:03:06602 'CallJavascriptFunctionUnsafe',
603 (
604 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
605 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
606 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
607 ),
608 False,
609 (
Egor Paskoce145c42018-09-28 19:31:04610 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
611 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
612 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06613 ),
614 ),
dskiba1474c2bfd62017-07-20 02:19:24615 (
616 'leveldb::DB::Open',
617 (
618 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
619 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
620 "Chrome's tracing, making their memory usage visible.",
621 ),
622 True,
623 (
624 r'^third_party/leveldatabase/.*\.(cc|h)$',
625 ),
Gabriel Charette0592c3a2017-07-26 12:02:04626 ),
627 (
Chris Mumfordc38afb62017-10-09 17:55:08628 'leveldb::NewMemEnv',
629 (
630 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58631 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
632 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08633 ),
634 True,
635 (
636 r'^third_party/leveldatabase/.*\.(cc|h)$',
637 ),
638 ),
639 (
Gabriel Charetted9839bc2017-07-29 14:17:47640 'RunLoop::QuitCurrent',
641 (
Robert Liao64b7ab22017-08-04 23:03:43642 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
643 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47644 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41645 False,
Gabriel Charetted9839bc2017-07-29 14:17:47646 (),
Gabriel Charettea44975052017-08-21 23:14:04647 ),
648 (
649 'base::ScopedMockTimeMessageLoopTaskRunner',
650 (
Gabriel Charette87cc1af2018-04-25 20:52:51651 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11652 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51653 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
654 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
655 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04656 ),
Gabriel Charette87cc1af2018-04-25 20:52:51657 False,
Gabriel Charettea44975052017-08-21 23:14:04658 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57659 ),
660 (
Dave Tapuska98199b612019-07-10 13:30:44661 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57662 (
663 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02664 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57665 ),
666 True,
667 (),
Francois Doray43670e32017-09-27 12:40:38668 ),
669 (
Peter Kasting991618a62019-06-17 22:00:09670 r'/\bstd::stoi\b',
671 (
672 'std::stoi uses exceptions to communicate results. ',
673 'Use base::StringToInt() instead.',
674 ),
675 True,
676 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
677 ),
678 (
679 r'/\bstd::stol\b',
680 (
681 'std::stol uses exceptions to communicate results. ',
682 'Use base::StringToInt() instead.',
683 ),
684 True,
685 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
686 ),
687 (
688 r'/\bstd::stoul\b',
689 (
690 'std::stoul uses exceptions to communicate results. ',
691 'Use base::StringToUint() instead.',
692 ),
693 True,
694 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
695 ),
696 (
697 r'/\bstd::stoll\b',
698 (
699 'std::stoll uses exceptions to communicate results. ',
700 'Use base::StringToInt64() instead.',
701 ),
702 True,
703 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
704 ),
705 (
706 r'/\bstd::stoull\b',
707 (
708 'std::stoull uses exceptions to communicate results. ',
709 'Use base::StringToUint64() instead.',
710 ),
711 True,
712 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
713 ),
714 (
715 r'/\bstd::stof\b',
716 (
717 'std::stof uses exceptions to communicate results. ',
718 'For locale-independent values, e.g. reading numbers from disk',
719 'profiles, use base::StringToDouble().',
720 'For user-visible values, parse using ICU.',
721 ),
722 True,
723 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
724 ),
725 (
726 r'/\bstd::stod\b',
727 (
728 'std::stod uses exceptions to communicate results. ',
729 'For locale-independent values, e.g. reading numbers from disk',
730 'profiles, use base::StringToDouble().',
731 'For user-visible values, parse using ICU.',
732 ),
733 True,
734 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
735 ),
736 (
737 r'/\bstd::stold\b',
738 (
739 'std::stold uses exceptions to communicate results. ',
740 'For locale-independent values, e.g. reading numbers from disk',
741 'profiles, use base::StringToDouble().',
742 'For user-visible values, parse using ICU.',
743 ),
744 True,
745 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
746 ),
747 (
Daniel Bratell69334cc2019-03-26 11:07:45748 r'/\bstd::to_string\b',
749 (
750 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09751 'For locale-independent strings, e.g. writing numbers to disk',
752 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45753 'For user-visible strings, use base::FormatNumber() and',
754 'the related functions in base/i18n/number_formatting.h.',
755 ),
Peter Kasting991618a62019-06-17 22:00:09756 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21757 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45758 ),
759 (
760 r'/\bstd::shared_ptr\b',
761 (
762 'std::shared_ptr should not be used. Use scoped_refptr instead.',
763 ),
764 True,
Andreas Haas63f58792019-11-07 10:56:44765 [_THIRD_PARTY_EXCEPT_BLINK,
766 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
767 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21768 ),
769 (
Peter Kasting991618a62019-06-17 22:00:09770 r'/\bstd::weak_ptr\b',
771 (
772 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
773 ),
774 True,
775 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
776 ),
777 (
Daniel Bratell609102be2019-03-27 20:53:21778 r'/\blong long\b',
779 (
780 'long long is banned. Use stdint.h if you need a 64 bit number.',
781 ),
782 False, # Only a warning since it is already used.
783 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
784 ),
785 (
786 r'/\bstd::bind\b',
787 (
788 'std::bind is banned because of lifetime risks.',
789 'Use base::BindOnce or base::BindRepeating instead.',
790 ),
791 True,
792 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
793 ),
794 (
795 r'/\b#include <chrono>\b',
796 (
797 '<chrono> overlaps with Time APIs in base. Keep using',
798 'base classes.',
799 ),
800 True,
801 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
802 ),
803 (
804 r'/\b#include <exception>\b',
805 (
806 'Exceptions are banned and disabled in Chromium.',
807 ),
808 True,
809 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
810 ),
811 (
812 r'/\bstd::function\b',
813 (
814 'std::function is banned. Instead use base::Callback which directly',
815 'supports Chromium\'s weak pointers, ref counting and more.',
816 ),
Peter Kasting991618a62019-06-17 22:00:09817 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21818 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
819 ),
820 (
821 r'/\b#include <random>\b',
822 (
823 'Do not use any random number engines from <random>. Instead',
824 'use base::RandomBitGenerator.',
825 ),
826 True,
827 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
828 ),
829 (
830 r'/\bstd::ratio\b',
831 (
832 'std::ratio is banned by the Google Style Guide.',
833 ),
834 True,
835 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45836 ),
837 (
Francois Doray43670e32017-09-27 12:40:38838 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
839 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
840 (
841 'Use the new API in base/threading/thread_restrictions.h.',
842 ),
Gabriel Charette04b138f2018-08-06 00:03:22843 False,
Francois Doray43670e32017-09-27 12:40:38844 (),
845 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38846 (
danakj7a2b7082019-05-21 21:13:51847 r'/\bbase::Bind\(',
848 (
849 'Please use base::Bind{Once,Repeating} instead',
850 'of base::Bind. (crbug.com/714018)',
851 ),
852 False,
Erik Staaba737d7602019-11-25 18:41:07853 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51854 ),
855 (
856 r'/\bbase::Callback[<:]',
857 (
858 'Please use base::{Once,Repeating}Callback instead',
859 'of base::Callback. (crbug.com/714018)',
860 ),
861 False,
Erik Staaba737d7602019-11-25 18:41:07862 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51863 ),
864 (
865 r'/\bbase::Closure\b',
866 (
867 'Please use base::{Once,Repeating}Closure instead',
868 'of base::Closure. (crbug.com/714018)',
869 ),
870 False,
Erik Staaba737d7602019-11-25 18:41:07871 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51872 ),
873 (
Michael Giuffrida7f93d6922019-04-19 14:39:58874 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19875 (
876 'RunMessageLoop is deprecated, use RunLoop instead.',
877 ),
878 False,
879 (),
880 ),
881 (
Dave Tapuska98199b612019-07-10 13:30:44882 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19883 (
884 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
885 ),
886 False,
887 (),
888 ),
889 (
Dave Tapuska98199b612019-07-10 13:30:44890 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19891 (
892 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
893 "if you're convinced you need this.",
894 ),
895 False,
896 (),
897 ),
898 (
Dave Tapuska98199b612019-07-10 13:30:44899 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19900 (
901 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04902 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19903 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
904 'async events instead of flushing threads.',
905 ),
906 False,
907 (),
908 ),
909 (
910 r'MessageLoopRunner',
911 (
912 'MessageLoopRunner is deprecated, use RunLoop instead.',
913 ),
914 False,
915 (),
916 ),
917 (
Dave Tapuska98199b612019-07-10 13:30:44918 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19919 (
920 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
921 "gab@ if you found a use case where this is the only solution.",
922 ),
923 False,
924 (),
925 ),
926 (
Victor Costane48a2e82019-03-15 22:02:34927 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16928 (
Victor Costane48a2e82019-03-15 22:02:34929 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16930 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
931 ),
932 True,
933 (
934 r'^sql/initialization\.(cc|h)$',
935 r'^third_party/sqlite/.*\.(c|cc|h)$',
936 ),
937 ),
Matt Menke7f520a82018-03-28 21:38:37938 (
939 'net::URLFetcher',
940 (
941 'net::URLFetcher should no longer be used in content embedders. ',
942 'Instead, use network::SimpleURLLoader instead, which supports ',
943 'an out-of-process network stack. ',
944 'net::URLFetcher may still be used in binaries that do not embed',
945 'content.',
946 ),
Matt Menke59716d02018-04-05 12:45:53947 False,
Matt Menke7f520a82018-03-28 21:38:37948 (
Egor Paskoce145c42018-09-28 19:31:04949 r'^ios[\\/].*\.(cc|h)$',
950 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37951 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04952 r'^net[\\/].*\.(cc|h)$',
953 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43954 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37955 ),
956 ),
jdoerried7d10ab2018-04-27 10:46:13957 (
Dave Tapuska98199b612019-07-10 13:30:44958 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47959 (
960 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
961 'base::RandomShuffle instead.'
962 ),
963 True,
964 (),
965 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24966 (
967 'ios/web/public/test/http_server',
968 (
969 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
970 ),
971 False,
972 (),
973 ),
Robert Liao764c9492019-01-24 18:46:28974 (
975 'GetAddressOf',
976 (
977 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46978 'implicated in a few leaks. Use operator& instead. See ',
979 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28980 ),
981 True,
982 (),
983 ),
Antonio Gomes07300d02019-03-13 20:59:57984 (
985 'DEFINE_TYPE_CASTS',
986 (
987 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
988 '//third_party/blink/renderer/platform/casting.h.'
989 ),
990 True,
991 (
992 r'^third_party/blink/renderer/.*\.(cc|h)$',
993 ),
994 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38995 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45996 r'/\bIsHTML.+Element\(\b',
997 (
998 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
999 ' helpers IsA<HTMLXXXXElement> from ',
1000 '//third_party/blink/renderer/platform/casting.h.'
1001 ),
1002 False,
1003 (
1004 r'^third_party/blink/renderer/.*\.(cc|h)$',
1005 ),
1006 ),
1007 (
1008 r'/\bToHTML.+Element(|OrNull)\(\b',
1009 (
1010 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1011 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1012 'and DynamicTo<HTMLXXXXElement> from ',
1013 '//third_party/blink/renderer/platform/casting.h.'
1014 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1015 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1016 ),
1017 False,
1018 (
1019 r'^third_party/blink/renderer/.*\.(cc|h)$',
1020 ),
1021 ),
1022 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371023 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381024 (
1025 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1026 ),
1027 True,
1028 (),
1029 ),
Ben Lewisa9514602019-04-29 17:53:051030 (
1031 'SHFileOperation',
1032 (
1033 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1034 'complex functions to achieve the same goals. Use IFileOperation for ',
1035 'any esoteric actions instead.'
1036 ),
1037 True,
1038 (),
1039 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181040 (
Cliff Smolinsky81951642019-04-30 21:39:511041 'StringFromGUID2',
1042 (
1043 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1044 'Use base::win::String16FromGUID instead.'
1045 ),
1046 True,
1047 (
1048 r'/base/win/win_util_unittest.cc'
1049 ),
1050 ),
1051 (
1052 'StringFromCLSID',
1053 (
1054 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1055 'Use base::win::String16FromGUID instead.'
1056 ),
1057 True,
1058 (
1059 r'/base/win/win_util_unittest.cc'
1060 ),
1061 ),
1062 (
Avi Drissman7382afa02019-04-29 23:27:131063 'kCFAllocatorNull',
1064 (
1065 'The use of kCFAllocatorNull with the NoCopy creation of ',
1066 'CoreFoundation types is prohibited.',
1067 ),
1068 True,
1069 (),
1070 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291071 (
1072 'mojo::ConvertTo',
1073 (
1074 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1075 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1076 'StringTraits if you would like to convert between custom types and',
1077 'the wire format of mojom types.'
1078 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221079 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291080 (
Wezf89dec092019-09-11 19:38:331081 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1082 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291083 r'^third_party/blink/.*\.(cc|h)$',
1084 r'^content/renderer/.*\.(cc|h)$',
1085 ),
1086 ),
Robert Liao1d78df52019-11-11 20:02:011087 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161088 'GetInterfaceProvider',
1089 (
1090 'InterfaceProvider is deprecated.',
1091 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1092 'or Platform::GetBrowserInterfaceBroker.'
1093 ),
1094 False,
1095 (),
1096 ),
1097 (
Robert Liao1d78df52019-11-11 20:02:011098 'CComPtr',
1099 (
1100 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1101 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1102 'details.'
1103 ),
1104 False,
1105 (),
1106 ),
Xiaohan Wang72bd2ba2020-02-18 21:38:201107 (
1108 r'/\b(IFACE|STD)METHOD_?\(',
1109 (
1110 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1111 'Instead, always use IFACEMETHODIMP in the declaration.'
1112 ),
1113 False,
1114 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1115 ),
[email protected]127f18ec2012-06-16 05:05:591116)
1117
Mario Sanchez Prada2472cab2019-09-18 10:58:311118# Format: Sequence of tuples containing:
1119# * String pattern or, if starting with a slash, a regular expression.
1120# * Sequence of strings to show when the pattern matches.
1121_DEPRECATED_MOJO_TYPES = (
1122 (
1123 r'/\bmojo::AssociatedBinding\b',
1124 (
1125 'mojo::AssociatedBinding<Interface> is deprecated.',
1126 'Use mojo::AssociatedReceiver<Interface> instead.',
1127 ),
1128 ),
1129 (
1130 r'/\bmojo::AssociatedBindingSet\b',
1131 (
1132 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1133 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1134 ),
1135 ),
1136 (
1137 r'/\bmojo::AssociatedInterfacePtr\b',
1138 (
1139 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1140 'Use mojo::AssociatedRemote<Interface> instead.',
1141 ),
1142 ),
1143 (
1144 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1145 (
1146 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1147 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1148 ),
1149 ),
1150 (
1151 r'/\bmojo::AssociatedInterfaceRequest\b',
1152 (
1153 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1154 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1155 ),
1156 ),
1157 (
1158 r'/\bmojo::Binding\b',
1159 (
1160 'mojo::Binding<Interface> is deprecated.',
1161 'Use mojo::Receiver<Interface> instead.',
1162 ),
1163 ),
1164 (
1165 r'/\bmojo::BindingSet\b',
1166 (
1167 'mojo::BindingSet<Interface> is deprecated.',
1168 'Use mojo::ReceiverSet<Interface> instead.',
1169 ),
1170 ),
1171 (
1172 r'/\bmojo::InterfacePtr\b',
1173 (
1174 'mojo::InterfacePtr<Interface> is deprecated.',
1175 'Use mojo::Remote<Interface> instead.',
1176 ),
1177 ),
1178 (
1179 r'/\bmojo::InterfacePtrInfo\b',
1180 (
1181 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1182 'Use mojo::PendingRemote<Interface> instead.',
1183 ),
1184 ),
1185 (
1186 r'/\bmojo::InterfaceRequest\b',
1187 (
1188 'mojo::InterfaceRequest<Interface> is deprecated.',
1189 'Use mojo::PendingReceiver<Interface> instead.',
1190 ),
1191 ),
1192 (
1193 r'/\bmojo::MakeRequest\b',
1194 (
1195 'mojo::MakeRequest is deprecated.',
1196 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1197 ),
1198 ),
1199 (
1200 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1201 (
1202 'mojo::MakeRequest is deprecated.',
1203 'Use mojo::AssociatedRemote::'
1204 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1205 ),
1206 ),
1207 (
1208 r'/\bmojo::MakeStrongBinding\b',
1209 (
1210 'mojo::MakeStrongBinding is deprecated.',
1211 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1212 'mojo::MakeSelfOwnedReceiver() instead.',
1213 ),
1214 ),
1215 (
1216 r'/\bmojo::MakeStrongAssociatedBinding\b',
1217 (
1218 'mojo::MakeStrongAssociatedBinding is deprecated.',
1219 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1220 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1221 ),
1222 ),
1223 (
1224 r'/\bmojo::StrongAssociatedBindingSet\b',
1225 (
1226 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1227 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1228 ),
1229 ),
1230 (
1231 r'/\bmojo::StrongBindingSet\b',
1232 (
1233 'mojo::StrongBindingSet<Interface> is deprecated.',
1234 'Use mojo::UniqueReceiverSet<Interface> instead.',
1235 ),
1236 ),
1237)
wnwenbdc444e2016-05-25 13:44:151238
mlamouria82272622014-09-16 18:45:041239_IPC_ENUM_TRAITS_DEPRECATED = (
1240 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501241 'See http://www.chromium.org/Home/chromium-security/education/'
1242 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041243
Stephen Martinis97a394142018-06-07 23:06:051244_LONG_PATH_ERROR = (
1245 'Some files included in this CL have file names that are too long (> 200'
1246 ' characters). If committed, these files will cause issues on Windows. See'
1247 ' https://crbug.com/612667 for more details.'
1248)
1249
Shenghua Zhangbfaa38b82017-11-16 21:58:021250_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041251 r".*[\\/]BuildHooksAndroidImpl\.java",
1252 r".*[\\/]LicenseContentProvider\.java",
1253 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281254 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021255]
[email protected]127f18ec2012-06-16 05:05:591256
Mohamed Heikald048240a2019-11-12 16:57:371257# List of image extensions that are used as resources in chromium.
1258_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1259
Sean Kau46e29bc2017-08-28 16:31:161260# These paths contain test data and other known invalid JSON files.
1261_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041262 r'test[\\/]data[\\/]',
1263 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1264 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041265 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431266 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161267]
1268
1269
[email protected]b00342e7f2013-03-26 16:21:541270_VALID_OS_MACROS = (
1271 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081272 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541273 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121274 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541275 'OS_BSD',
1276 'OS_CAT', # For testing.
1277 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041278 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371280 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541281 'OS_IOS',
1282 'OS_LINUX',
1283 'OS_MACOSX',
1284 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211285 'OS_NACL_NONSFI',
1286 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121287 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541288 'OS_OPENBSD',
1289 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371290 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541291 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541292 'OS_WIN',
1293)
1294
1295
agrievef32bcc72016-04-04 14:57:401296_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391297 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361298 'base/android/jni_generator/jni_generator.pydeps',
1299 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221300 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361301 'build/android/gyp/aar.pydeps',
1302 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271303 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381305 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361306 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111307 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361309 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361310 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111311 'build/android/gyp/create_app_bundle_apks.pydeps',
1312 'build/android/gyp/create_app_bundle.pydeps',
1313 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361314 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221315 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361316 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591317 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361318 'build/android/gyp/dex.pydeps',
1319 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361320 'build/android/gyp/filter_zip.pydeps',
1321 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361322 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361323 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581324 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361325 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261326 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve5853fbd2020-02-20 17:26:011327 'build/android/gyp/jetify_jar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361328 'build/android/gyp/jinja_template.pydeps',
1329 'build/android/gyp/lint.pydeps',
1330 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361331 'build/android/gyp/merge_manifest.pydeps',
1332 'build/android/gyp/prepare_resources.pydeps',
1333 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241334 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361335 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461336 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561337 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361338 'build/android/incremental_install/generate_android_manifest.pydeps',
1339 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221340 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401341 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041342 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361343 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411344 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051345 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191346 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431347 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021348 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401349]
1350
wnwenbdc444e2016-05-25 13:44:151351
agrievef32bcc72016-04-04 14:57:401352_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421353 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131354 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421355 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1356 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131357 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191358 ('third_party/blink/renderer/bindings/scripts/'
1359 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061360 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221361 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401362]
1363
wnwenbdc444e2016-05-25 13:44:151364
agrievef32bcc72016-04-04 14:57:401365_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1366
1367
Eric Boren6fd2b932018-01-25 15:05:081368# Bypass the AUTHORS check for these accounts.
1369_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591370 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451371 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591372 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521373 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1374 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041375 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271376 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041377 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301378 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081379
1380
Daniel Bratell65b033262019-04-23 08:17:061381def _IsCPlusPlusFile(input_api, file_path):
1382 """Returns True if this file contains C++-like code (and not Python,
1383 Go, Java, MarkDown, ...)"""
1384
1385 ext = input_api.os_path.splitext(file_path)[1]
1386 # This list is compatible with CppChecker.IsCppFile but we should
1387 # consider adding ".c" to it. If we do that we can use this function
1388 # at more places in the code.
1389 return ext in (
1390 '.h',
1391 '.cc',
1392 '.cpp',
1393 '.m',
1394 '.mm',
1395 )
1396
1397def _IsCPlusPlusHeaderFile(input_api, file_path):
1398 return input_api.os_path.splitext(file_path)[1] == ".h"
1399
1400
1401def _IsJavaFile(input_api, file_path):
1402 return input_api.os_path.splitext(file_path)[1] == ".java"
1403
1404
1405def _IsProtoFile(input_api, file_path):
1406 return input_api.os_path.splitext(file_path)[1] == ".proto"
1407
[email protected]55459852011-08-10 15:17:191408def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1409 """Attempts to prevent use of functions intended only for testing in
1410 non-testing code. For now this is just a best-effort implementation
1411 that ignores header files and may have some false positives. A
1412 better implementation would probably need a proper C++ parser.
1413 """
1414 # We only scan .cc files and the like, as the declaration of
1415 # for-testing functions in header files are hard to distinguish from
1416 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491417 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191418
jochenc0d4808c2015-07-27 09:25:421419 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191420 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091421 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191422 exclusion_pattern = input_api.re.compile(
1423 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1424 base_function_pattern, base_function_pattern))
1425
1426 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441427 black_list = (_EXCLUDED_PATHS +
1428 _TEST_CODE_EXCLUDED_PATHS +
1429 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191430 return input_api.FilterSourceFile(
1431 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491432 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191433 black_list=black_list)
1434
1435 problems = []
1436 for f in input_api.AffectedSourceFiles(FilterFile):
1437 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241438 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031439 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461440 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031441 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191442 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031443 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191444
1445 if problems:
[email protected]f7051d52013-04-02 18:31:421446 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031447 else:
1448 return []
[email protected]55459852011-08-10 15:17:191449
1450
Vaclav Brozek7dbc28c2018-03-27 08:35:231451def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1452 """This is a simplified version of
1453 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1454 """
1455 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1456 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1457 name_pattern = r'ForTest(s|ing)?'
1458 # Describes an occurrence of "ForTest*" inside a // comment.
1459 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1460 # Catch calls.
1461 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1462 # Ignore definitions. (Comments are ignored separately.)
1463 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1464
1465 problems = []
1466 sources = lambda x: input_api.FilterSourceFile(
1467 x,
1468 black_list=(('(?i).*test', r'.*\/junit\/')
1469 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491470 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231471 )
1472 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1473 local_path = f.LocalPath()
1474 is_inside_javadoc = False
1475 for line_number, line in f.ChangedContents():
1476 if is_inside_javadoc and javadoc_end_re.search(line):
1477 is_inside_javadoc = False
1478 if not is_inside_javadoc and javadoc_start_re.search(line):
1479 is_inside_javadoc = True
1480 if is_inside_javadoc:
1481 continue
1482 if (inclusion_re.search(line) and
1483 not comment_re.search(line) and
1484 not exclusion_re.search(line)):
1485 problems.append(
1486 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1487
1488 if problems:
1489 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1490 else:
1491 return []
1492
1493
[email protected]10689ca2011-09-02 02:31:541494def _CheckNoIOStreamInHeaders(input_api, output_api):
1495 """Checks to make sure no .h files include <iostream>."""
1496 files = []
1497 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1498 input_api.re.MULTILINE)
1499 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1500 if not f.LocalPath().endswith('.h'):
1501 continue
1502 contents = input_api.ReadFile(f)
1503 if pattern.search(contents):
1504 files.append(f)
1505
1506 if len(files):
yolandyandaabc6d2016-04-18 18:29:391507 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061508 'Do not #include <iostream> in header files, since it inserts static '
1509 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541510 '#include <ostream>. See http://crbug.com/94794',
1511 files) ]
1512 return []
1513
Danil Chapovalov3518f362018-08-11 16:13:431514def _CheckNoStrCatRedefines(input_api, output_api):
1515 """Checks no windows headers with StrCat redefined are included directly."""
1516 files = []
1517 pattern_deny = input_api.re.compile(
1518 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1519 input_api.re.MULTILINE)
1520 pattern_allow = input_api.re.compile(
1521 r'^#include\s"base/win/windows_defines.inc"',
1522 input_api.re.MULTILINE)
1523 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1524 contents = input_api.ReadFile(f)
1525 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1526 files.append(f.LocalPath())
1527
1528 if len(files):
1529 return [output_api.PresubmitError(
1530 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1531 'directly since they pollute code with StrCat macro. Instead, '
1532 'include matching header from base/win. See http://crbug.com/856536',
1533 files) ]
1534 return []
1535
[email protected]10689ca2011-09-02 02:31:541536
[email protected]72df4e782012-06-21 16:28:181537def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521538 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181539 problems = []
1540 for f in input_api.AffectedFiles():
1541 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1542 continue
1543
1544 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041545 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181546 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1547
1548 if not problems:
1549 return []
1550 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1551 '\n'.join(problems))]
1552
Dominic Battre033531052018-09-24 15:45:341553def _CheckNoDISABLETypoInTests(input_api, output_api):
1554 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1555
1556 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1557 instead of DISABLED_. To filter false positives, reports are only generated
1558 if a corresponding MAYBE_ line exists.
1559 """
1560 problems = []
1561
1562 # The following two patterns are looked for in tandem - is a test labeled
1563 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1564 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1565 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1566
1567 # This is for the case that a test is disabled on all platforms.
1568 full_disable_pattern = input_api.re.compile(
1569 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1570 input_api.re.MULTILINE)
1571
Katie Df13948e2018-09-25 07:33:441572 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341573 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1574 continue
1575
1576 # Search for MABYE_, DISABLE_ pairs.
1577 disable_lines = {} # Maps of test name to line number.
1578 maybe_lines = {}
1579 for line_num, line in f.ChangedContents():
1580 disable_match = disable_pattern.search(line)
1581 if disable_match:
1582 disable_lines[disable_match.group(1)] = line_num
1583 maybe_match = maybe_pattern.search(line)
1584 if maybe_match:
1585 maybe_lines[maybe_match.group(1)] = line_num
1586
1587 # Search for DISABLE_ occurrences within a TEST() macro.
1588 disable_tests = set(disable_lines.keys())
1589 maybe_tests = set(maybe_lines.keys())
1590 for test in disable_tests.intersection(maybe_tests):
1591 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1592
1593 contents = input_api.ReadFile(f)
1594 full_disable_match = full_disable_pattern.search(contents)
1595 if full_disable_match:
1596 problems.append(' %s' % f.LocalPath())
1597
1598 if not problems:
1599 return []
1600 return [
1601 output_api.PresubmitPromptWarning(
1602 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1603 '\n'.join(problems))
1604 ]
1605
[email protected]72df4e782012-06-21 16:28:181606
danakj61c1aa22015-10-26 19:55:521607def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571608 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521609 errors = []
1610 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1611 input_api.re.MULTILINE)
1612 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1613 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1614 continue
1615 for lnum, line in f.ChangedContents():
1616 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171617 errors.append(output_api.PresubmitError(
1618 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571619 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171620 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521621 return errors
1622
1623
Makoto Shimazu3ad422cd2019-05-08 02:35:141624def _FindHistogramNameInChunk(histogram_name, chunk):
1625 """Tries to find a histogram name or prefix in a line.
1626
1627 Returns the existence of the histogram name, or None if it needs more chunk
1628 to determine."""
mcasasb7440c282015-02-04 14:52:191629 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1630 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141631 if '<affected-histogram' in chunk:
1632 # If the tag is not completed, needs more chunk to get the name.
1633 if not '>' in chunk:
1634 return None
1635 if not 'name="' in chunk:
1636 return False
1637 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1638 # expect the only attribute is the name.
1639 histogram_prefix = chunk.split('"')[1]
1640 return histogram_prefix in histogram_name
1641 # Typically the whole histogram name should in the line.
1642 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191643
1644
1645def _CheckUmaHistogramChanges(input_api, output_api):
1646 """Check that UMA histogram names in touched lines can still be found in other
1647 lines of the patch or in histograms.xml. Note that this check would not catch
1648 the reverse: changes in histograms.xml not matched in the code itself."""
1649 touched_histograms = []
1650 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471651 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1652 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1653 name_pattern = r'"(.*?)"'
1654 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1655 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1656 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1657 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1658 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171659 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191660 for f in input_api.AffectedFiles():
1661 # If histograms.xml itself is modified, keep the modified lines for later.
1662 if f.LocalPath().endswith(('histograms.xml')):
1663 histograms_xml_modifications = f.ChangedContents()
1664 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471665 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1666 single_line_re = single_line_c_re
1667 split_line_prefix_re = split_line_c_prefix_re
1668 elif f.LocalPath().endswith(('java')):
1669 single_line_re = single_line_java_re
1670 split_line_prefix_re = split_line_java_prefix_re
1671 else:
mcasasb7440c282015-02-04 14:52:191672 continue
1673 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171674 if last_line_matched_prefix:
1675 suffix_found = split_line_suffix_re.search(line)
1676 if suffix_found :
1677 touched_histograms.append([suffix_found.group(1), f, line_num])
1678 last_line_matched_prefix = False
1679 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061680 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191681 if found:
1682 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171683 continue
1684 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191685
1686 # Search for the touched histogram names in the local modifications to
1687 # histograms.xml, and, if not found, on the base histograms.xml file.
1688 unmatched_histograms = []
1689 for histogram_info in touched_histograms:
1690 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141691 chunk = ''
mcasasb7440c282015-02-04 14:52:191692 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141693 chunk += line
1694 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], 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 unmatched_histograms.append(histogram_info)
1702
eromanb90c82e7e32015-04-01 15:13:491703 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191704 problems = []
1705 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491706 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191707 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451708 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191709 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141710 chunk = ''
mcasasb7440c282015-02-04 14:52:191711 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141712 chunk += line
1713 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1714 chunk)
1715 if histogram_name_found is None:
1716 continue
1717 chunk = ''
mcasasb7440c282015-02-04 14:52:191718 if histogram_name_found:
1719 break
1720 if not histogram_name_found:
1721 problems.append(' [%s:%d] %s' %
1722 (f.LocalPath(), line_num, histogram_name))
1723
1724 if not problems:
1725 return []
1726 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1727 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491728 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191729
wnwenbdc444e2016-05-25 13:44:151730
yolandyandaabc6d2016-04-18 18:29:391731def _CheckFlakyTestUsage(input_api, output_api):
1732 """Check that FlakyTest annotation is our own instead of the android one"""
1733 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1734 files = []
1735 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1736 if f.LocalPath().endswith('Test.java'):
1737 if pattern.search(input_api.ReadFile(f)):
1738 files.append(f)
1739 if len(files):
1740 return [output_api.PresubmitError(
1741 'Use org.chromium.base.test.util.FlakyTest instead of '
1742 'android.test.FlakyTest',
1743 files)]
1744 return []
mcasasb7440c282015-02-04 14:52:191745
wnwenbdc444e2016-05-25 13:44:151746
[email protected]8ea5d4b2011-09-13 21:49:221747def _CheckNoNewWStrings(input_api, output_api):
1748 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271749 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221750 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201751 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571752 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341753 '/win/' in f.LocalPath() or
1754 'chrome_elf' in f.LocalPath() or
1755 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201756 continue
[email protected]8ea5d4b2011-09-13 21:49:221757
[email protected]a11dbe9b2012-08-07 01:32:581758 allowWString = False
[email protected]b5c24292011-11-28 14:38:201759 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581760 if 'presubmit: allow wstring' in line:
1761 allowWString = True
1762 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271763 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581764 allowWString = False
1765 else:
1766 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221767
[email protected]55463aa62011-10-12 00:48:271768 if not problems:
1769 return []
1770 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581771 ' If you are calling a cross-platform API that accepts a wstring, '
1772 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271773 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221774
1775
[email protected]2a8ac9c2011-10-19 17:20:441776def _CheckNoDEPSGIT(input_api, output_api):
1777 """Make sure .DEPS.git is never modified manually."""
1778 if any(f.LocalPath().endswith('.DEPS.git') for f in
1779 input_api.AffectedFiles()):
1780 return [output_api.PresubmitError(
1781 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1782 'automated system based on what\'s in DEPS and your changes will be\n'
1783 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501784 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1785 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441786 'for more information')]
1787 return []
1788
1789
tandriief664692014-09-23 14:51:471790def _CheckValidHostsInDEPS(input_api, output_api):
1791 """Checks that DEPS file deps are from allowed_hosts."""
1792 # Run only if DEPS file has been modified to annoy fewer bystanders.
1793 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1794 return []
1795 # Outsource work to gclient verify
1796 try:
John Budorickf20c0042019-04-25 23:23:401797 gclient_path = input_api.os_path.join(
1798 input_api.PresubmitLocalPath(),
1799 'third_party', 'depot_tools', 'gclient.py')
1800 input_api.subprocess.check_output(
1801 [input_api.python_executable, gclient_path, 'verify'],
1802 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471803 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201804 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471805 return [output_api.PresubmitError(
1806 'DEPS file must have only git dependencies.',
1807 long_text=error.output)]
1808
1809
Mario Sanchez Prada2472cab2019-09-18 10:58:311810def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1811 type_name, message):
1812 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1813
1814 Returns an string composed of the name of the file, the line number where the
1815 match has been found and the additional text passed as |message| in case the
1816 target type name matches the text inside the line passed as parameter.
1817 """
1818 matched = False
1819 if type_name[0:1] == '/':
1820 regex = type_name[1:]
1821 if input_api.re.search(regex, line):
1822 matched = True
1823 elif type_name in line:
1824 matched = True
1825
1826 result = []
1827 if matched:
1828 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1829 for message_line in message:
1830 result.append(' %s' % message_line)
1831
1832 return result
1833
1834
[email protected]127f18ec2012-06-16 05:05:591835def _CheckNoBannedFunctions(input_api, output_api):
1836 """Make sure that banned functions are not used."""
1837 warnings = []
1838 errors = []
1839
wnwenbdc444e2016-05-25 13:44:151840 def IsBlacklisted(affected_file, blacklist):
1841 local_path = affected_file.LocalPath()
1842 for item in blacklist:
1843 if input_api.re.match(item, local_path):
1844 return True
1845 return False
1846
Peter K. Lee6c03ccff2019-07-15 14:40:051847 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541848 local_path = affected_file.LocalPath()
1849 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1850 return False
1851 basename = input_api.os_path.basename(local_path)
1852 if 'ios' in basename.split('_'):
1853 return True
1854 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1855 if sep and 'ios' in local_path.split(sep):
1856 return True
1857 return False
1858
wnwenbdc444e2016-05-25 13:44:151859 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311860 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1861 func_name, message)
1862 if problems:
wnwenbdc444e2016-05-25 13:44:151863 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311864 errors.extend(problems)
1865 else:
1866 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151867
Eric Stevensona9a980972017-09-23 00:04:411868 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1869 for f in input_api.AffectedFiles(file_filter=file_filter):
1870 for line_num, line in f.ChangedContents():
1871 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1872 CheckForMatch(f, line_num, line, func_name, message, error)
1873
[email protected]127f18ec2012-06-16 05:05:591874 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1875 for f in input_api.AffectedFiles(file_filter=file_filter):
1876 for line_num, line in f.ChangedContents():
1877 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151878 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591879
Peter K. Lee6c03ccff2019-07-15 14:40:051880 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541881 for line_num, line in f.ChangedContents():
1882 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1883 CheckForMatch(f, line_num, line, func_name, message, error)
1884
Peter K. Lee6c03ccff2019-07-15 14:40:051885 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1886 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1887 for line_num, line in f.ChangedContents():
1888 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1889 CheckForMatch(f, line_num, line, func_name, message, error)
1890
[email protected]127f18ec2012-06-16 05:05:591891 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1892 for f in input_api.AffectedFiles(file_filter=file_filter):
1893 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491894 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491895 if IsBlacklisted(f, excluded_paths):
1896 continue
wnwenbdc444e2016-05-25 13:44:151897 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591898
1899 result = []
1900 if (warnings):
1901 result.append(output_api.PresubmitPromptWarning(
1902 'Banned functions were used.\n' + '\n'.join(warnings)))
1903 if (errors):
1904 result.append(output_api.PresubmitError(
1905 'Banned functions were used.\n' + '\n'.join(errors)))
1906 return result
1907
1908
Michael Thiessen44457642020-02-06 00:24:151909def _CheckAndroidNoBannedImports(input_api, output_api):
1910 """Make sure that banned java imports are not used."""
1911 errors = []
1912
1913 def IsException(path, exceptions):
1914 for exception in exceptions:
1915 if (path.startswith(exception)):
1916 return True
1917 return False
1918
1919 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1920 for f in input_api.AffectedFiles(file_filter=file_filter):
1921 for line_num, line in f.ChangedContents():
1922 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1923 if IsException(f.LocalPath(), exceptions):
1924 continue;
1925 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1926 'import ' + import_name, message)
1927 if problems:
1928 errors.extend(problems)
1929 result = []
1930 if (errors):
1931 result.append(output_api.PresubmitError(
1932 'Banned imports were used.\n' + '\n'.join(errors)))
1933 return result
1934
1935
Mario Sanchez Prada2472cab2019-09-18 10:58:311936def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1937 """Make sure that old Mojo types are not used."""
1938 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571939 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311940
Mario Sanchez Pradaaab91382019-12-19 08:57:091941 # For any path that is not an "ok" or an "error" path, a warning will be
1942 # raised if deprecated mojo types are found.
1943 ok_paths = ['components/arc']
1944 error_paths = ['third_party/blink', 'content']
1945
Mario Sanchez Prada2472cab2019-09-18 10:58:311946 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1947 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571948 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091949 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311950 continue
1951
1952 for line_num, line in f.ChangedContents():
1953 for func_name, message in _DEPRECATED_MOJO_TYPES:
1954 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1955 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571956
Mario Sanchez Prada2472cab2019-09-18 10:58:311957 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091958 # Raise errors inside |error_paths| and warnings everywhere else.
1959 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571960 errors.extend(problems)
1961 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311962 warnings.extend(problems)
1963
1964 result = []
1965 if (warnings):
1966 result.append(output_api.PresubmitPromptWarning(
1967 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571968 if (errors):
1969 result.append(output_api.PresubmitError(
1970 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311971 return result
1972
1973
[email protected]6c063c62012-07-11 19:11:061974def _CheckNoPragmaOnce(input_api, output_api):
1975 """Make sure that banned functions are not used."""
1976 files = []
1977 pattern = input_api.re.compile(r'^#pragma\s+once',
1978 input_api.re.MULTILINE)
1979 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1980 if not f.LocalPath().endswith('.h'):
1981 continue
1982 contents = input_api.ReadFile(f)
1983 if pattern.search(contents):
1984 files.append(f)
1985
1986 if files:
1987 return [output_api.PresubmitError(
1988 'Do not use #pragma once in header files.\n'
1989 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1990 files)]
1991 return []
1992
[email protected]127f18ec2012-06-16 05:05:591993
[email protected]e7479052012-09-19 00:26:121994def _CheckNoTrinaryTrueFalse(input_api, output_api):
1995 """Checks to make sure we don't introduce use of foo ? true : false."""
1996 problems = []
1997 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1998 for f in input_api.AffectedFiles():
1999 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2000 continue
2001
2002 for line_num, line in f.ChangedContents():
2003 if pattern.match(line):
2004 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2005
2006 if not problems:
2007 return []
2008 return [output_api.PresubmitPromptWarning(
2009 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2010 '\n'.join(problems))]
2011
2012
[email protected]55f9f382012-07-31 11:02:182013def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282014 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182015 change. Breaking - rules is an error, breaking ! rules is a
2016 warning.
2017 """
mohan.reddyf21db962014-10-16 12:26:472018 import sys
[email protected]55f9f382012-07-31 11:02:182019 # We need to wait until we have an input_api object and use this
2020 # roundabout construct to import checkdeps because this file is
2021 # eval-ed and thus doesn't have __file__.
2022 original_sys_path = sys.path
2023 try:
2024 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472025 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182026 import checkdeps
[email protected]55f9f382012-07-31 11:02:182027 from rules import Rule
2028 finally:
2029 # Restore sys.path to what it was before.
2030 sys.path = original_sys_path
2031
2032 added_includes = []
rhalavati08acd232017-04-03 07:23:282033 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242034 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182035 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062036 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502037 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082038 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062039 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502040 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082041 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062042 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502043 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082044 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182045
[email protected]26385172013-05-09 23:11:352046 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182047
2048 error_descriptions = []
2049 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282050 error_subjects = set()
2051 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182052 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2053 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082054 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182055 description_with_path = '%s\n %s' % (path, rule_description)
2056 if rule_type == Rule.DISALLOW:
2057 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282058 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182059 else:
2060 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282061 warning_subjects.add("#includes")
2062
2063 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2064 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082065 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282066 description_with_path = '%s\n %s' % (path, rule_description)
2067 if rule_type == Rule.DISALLOW:
2068 error_descriptions.append(description_with_path)
2069 error_subjects.add("imports")
2070 else:
2071 warning_descriptions.append(description_with_path)
2072 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182073
Jinsuk Kim5a092672017-10-24 22:42:242074 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022075 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082076 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242077 description_with_path = '%s\n %s' % (path, rule_description)
2078 if rule_type == Rule.DISALLOW:
2079 error_descriptions.append(description_with_path)
2080 error_subjects.add("imports")
2081 else:
2082 warning_descriptions.append(description_with_path)
2083 warning_subjects.add("imports")
2084
[email protected]55f9f382012-07-31 11:02:182085 results = []
2086 if error_descriptions:
2087 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282088 'You added one or more %s that violate checkdeps rules.'
2089 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182090 error_descriptions))
2091 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422092 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282093 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182094 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282095 '%s? See relevant DEPS file(s) for details and contacts.' %
2096 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182097 warning_descriptions))
2098 return results
2099
2100
[email protected]fbcafe5a2012-08-08 15:31:222101def _CheckFilePermissions(input_api, output_api):
2102 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152103 if input_api.platform == 'win32':
2104 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292105 checkperms_tool = input_api.os_path.join(
2106 input_api.PresubmitLocalPath(),
2107 'tools', 'checkperms', 'checkperms.py')
2108 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472109 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392110 with input_api.CreateTemporaryFile() as file_list:
2111 for f in input_api.AffectedFiles():
2112 # checkperms.py file/directory arguments must be relative to the
2113 # repository.
2114 file_list.write(f.LocalPath() + '\n')
2115 file_list.close()
2116 args += ['--file-list', file_list.name]
2117 try:
2118 input_api.subprocess.check_output(args)
2119 return []
2120 except input_api.subprocess.CalledProcessError as error:
2121 return [output_api.PresubmitError(
2122 'checkperms.py failed:',
2123 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222124
2125
robertocn832f5992017-01-04 19:01:302126def _CheckTeamTags(input_api, output_api):
2127 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2128 checkteamtags_tool = input_api.os_path.join(
2129 input_api.PresubmitLocalPath(),
2130 'tools', 'checkteamtags', 'checkteamtags.py')
2131 args = [input_api.python_executable, checkteamtags_tool,
2132 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222133 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302134 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2135 'OWNERS']
2136 try:
2137 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052138 warnings = input_api.subprocess.check_output(args + files).splitlines()
2139 if warnings:
2140 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302141 return []
2142 except input_api.subprocess.CalledProcessError as error:
2143 return [output_api.PresubmitError(
2144 'checkteamtags.py failed:',
2145 long_text=error.output)]
2146
2147
[email protected]c8278b32012-10-30 20:35:492148def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2149 """Makes sure we don't include ui/aura/window_property.h
2150 in header files.
2151 """
2152 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2153 errors = []
2154 for f in input_api.AffectedFiles():
2155 if not f.LocalPath().endswith('.h'):
2156 continue
2157 for line_num, line in f.ChangedContents():
2158 if pattern.match(line):
2159 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2160
2161 results = []
2162 if errors:
2163 results.append(output_api.PresubmitError(
2164 'Header files should not include ui/aura/window_property.h', errors))
2165 return results
2166
2167
[email protected]70ca77752012-11-20 03:45:032168def _CheckForVersionControlConflictsInFile(input_api, f):
2169 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2170 errors = []
2171 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162172 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232173 # First-level headers in markdown look a lot like version control
2174 # conflict markers. http://daringfireball.net/projects/markdown/basics
2175 continue
[email protected]70ca77752012-11-20 03:45:032176 if pattern.match(line):
2177 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2178 return errors
2179
2180
2181def _CheckForVersionControlConflicts(input_api, output_api):
2182 """Usually this is not intentional and will cause a compile failure."""
2183 errors = []
2184 for f in input_api.AffectedFiles():
2185 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2186
2187 results = []
2188 if errors:
2189 results.append(output_api.PresubmitError(
2190 'Version control conflict markers found, please resolve.', errors))
2191 return results
2192
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202193
estadee17314a02017-01-12 16:22:162194def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2195 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2196 errors = []
2197 for f in input_api.AffectedFiles():
2198 for line_num, line in f.ChangedContents():
2199 if pattern.search(line):
2200 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2201
2202 results = []
2203 if errors:
2204 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502205 'Found Google support URL addressed by answer number. Please replace '
2206 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162207 return results
2208
[email protected]70ca77752012-11-20 03:45:032209
[email protected]06e6d0ff2012-12-11 01:36:442210def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2211 def FilterFile(affected_file):
2212 """Filter function for use with input_api.AffectedSourceFiles,
2213 below. This filters out everything except non-test files from
2214 top-level directories that generally speaking should not hard-code
2215 service URLs (e.g. src/android_webview/, src/content/ and others).
2216 """
2217 return input_api.FilterSourceFile(
2218 affected_file,
Egor Paskoce145c42018-09-28 19:31:042219 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442220 black_list=(_EXCLUDED_PATHS +
2221 _TEST_CODE_EXCLUDED_PATHS +
2222 input_api.DEFAULT_BLACK_LIST))
2223
reillyi38965732015-11-16 18:27:332224 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2225 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462226 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2227 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442228 problems = [] # items are (filename, line_number, line)
2229 for f in input_api.AffectedSourceFiles(FilterFile):
2230 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462231 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442232 problems.append((f.LocalPath(), line_num, line))
2233
2234 if problems:
[email protected]f7051d52013-04-02 18:31:422235 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442236 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582237 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442238 [' %s:%d: %s' % (
2239 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032240 else:
2241 return []
[email protected]06e6d0ff2012-12-11 01:36:442242
2243
James Cook6b6597c2019-11-06 22:05:292244def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2245 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2246 def FileFilter(affected_file):
2247 """Includes directories known to be Chrome OS only."""
2248 return input_api.FilterSourceFile(
2249 affected_file,
2250 white_list=('^ash/',
2251 '^chromeos/', # Top-level src/chromeos.
2252 '/chromeos/', # Any path component.
2253 '^components/arc',
2254 '^components/exo'),
2255 black_list=(input_api.DEFAULT_BLACK_LIST))
2256
2257 prefs = []
2258 priority_prefs = []
2259 for f in input_api.AffectedFiles(file_filter=FileFilter):
2260 for line_num, line in f.ChangedContents():
2261 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2262 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2263 prefs.append(' %s' % line)
2264 if input_api.re.search(
2265 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2266 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2267 priority_prefs.append(' %s' % line)
2268
2269 results = []
2270 if (prefs):
2271 results.append(output_api.PresubmitPromptWarning(
2272 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2273 'by browser sync settings. If these prefs should be controlled by OS '
2274 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2275 if (priority_prefs):
2276 results.append(output_api.PresubmitPromptWarning(
2277 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2278 'controlled by browser sync settings. If these prefs should be '
2279 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2280 'instead.\n' + '\n'.join(prefs)))
2281 return results
2282
2283
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492284# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272285def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2286 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312287 The native_client_sdk directory is excluded because it has auto-generated PNG
2288 files for documentation.
[email protected]d2530012013-01-25 16:39:272289 """
[email protected]d2530012013-01-25 16:39:272290 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492291 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042292 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312293 file_filter = lambda f: input_api.FilterSourceFile(
2294 f, white_list=white_list, black_list=black_list)
2295 for f in input_api.AffectedFiles(include_deletes=False,
2296 file_filter=file_filter):
2297 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272298
2299 results = []
2300 if errors:
2301 results.append(output_api.PresubmitError(
2302 'The name of PNG files should not have abbreviations. \n'
2303 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2304 'Contact [email protected] if you have questions.', errors))
2305 return results
2306
2307
Daniel Cheng4dcdb6b2017-04-13 08:30:172308def _ExtractAddRulesFromParsedDeps(parsed_deps):
2309 """Extract the rules that add dependencies from a parsed DEPS file.
2310
2311 Args:
2312 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2313 add_rules = set()
2314 add_rules.update([
2315 rule[1:] for rule in parsed_deps.get('include_rules', [])
2316 if rule.startswith('+') or rule.startswith('!')
2317 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502318 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172319 {}).iteritems():
2320 add_rules.update([
2321 rule[1:] for rule in rules
2322 if rule.startswith('+') or rule.startswith('!')
2323 ])
2324 return add_rules
2325
2326
2327def _ParseDeps(contents):
2328 """Simple helper for parsing DEPS files."""
2329 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172330 class _VarImpl:
2331
2332 def __init__(self, local_scope):
2333 self._local_scope = local_scope
2334
2335 def Lookup(self, var_name):
2336 """Implements the Var syntax."""
2337 try:
2338 return self._local_scope['vars'][var_name]
2339 except KeyError:
2340 raise Exception('Var is not defined: %s' % var_name)
2341
2342 local_scope = {}
2343 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172344 'Var': _VarImpl(local_scope).Lookup,
2345 }
2346 exec contents in global_scope, local_scope
2347 return local_scope
2348
2349
2350def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082351 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412352 a set of DEPS entries that we should look up.
2353
2354 For a directory (rather than a specific filename) we fake a path to
2355 a specific filename by adding /DEPS. This is chosen as a file that
2356 will seldom or never be subject to per-file include_rules.
2357 """
[email protected]2b438d62013-11-14 17:54:142358 # We ignore deps entries on auto-generated directories.
2359 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082360
Daniel Cheng4dcdb6b2017-04-13 08:30:172361 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2362 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2363
2364 added_deps = new_deps.difference(old_deps)
2365
[email protected]2b438d62013-11-14 17:54:142366 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172367 for added_dep in added_deps:
2368 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2369 continue
2370 # Assume that a rule that ends in .h is a rule for a specific file.
2371 if added_dep.endswith('.h'):
2372 results.add(added_dep)
2373 else:
2374 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082375 return results
2376
2377
[email protected]e871964c2013-05-13 14:14:552378def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2379 """When a dependency prefixed with + is added to a DEPS file, we
2380 want to make sure that the change is reviewed by an OWNER of the
2381 target file or directory, to avoid layering violations from being
2382 introduced. This check verifies that this happens.
2383 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172384 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242385
2386 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492387 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242388 for f in input_api.AffectedFiles(include_deletes=False,
2389 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552390 filename = input_api.os_path.basename(f.LocalPath())
2391 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172392 virtual_depended_on_files.update(_CalculateAddedDeps(
2393 input_api.os_path,
2394 '\n'.join(f.OldContents()),
2395 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552396
[email protected]e871964c2013-05-13 14:14:552397 if not virtual_depended_on_files:
2398 return []
2399
2400 if input_api.is_committing:
2401 if input_api.tbr:
2402 return [output_api.PresubmitNotifyResult(
2403 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272404 if input_api.dry_run:
2405 return [output_api.PresubmitNotifyResult(
2406 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552407 if not input_api.change.issue:
2408 return [output_api.PresubmitError(
2409 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402410 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552411 output = output_api.PresubmitError
2412 else:
2413 output = output_api.PresubmitNotifyResult
2414
2415 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502416 owner_email, reviewers = (
2417 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2418 input_api,
2419 owners_db.email_regexp,
2420 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552421
2422 owner_email = owner_email or input_api.change.author_email
2423
[email protected]de4f7d22013-05-23 14:27:462424 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512425 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462426 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552427 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2428 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412429
2430 # We strip the /DEPS part that was added by
2431 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2432 # directory.
2433 def StripDeps(path):
2434 start_deps = path.rfind('/DEPS')
2435 if start_deps != -1:
2436 return path[:start_deps]
2437 else:
2438 return path
2439 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552440 for path in missing_files]
2441
2442 if unapproved_dependencies:
2443 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152444 output('You need LGTM from owners of depends-on paths in DEPS that were '
2445 'modified in this CL:\n %s' %
2446 '\n '.join(sorted(unapproved_dependencies)))]
2447 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2448 output_list.append(output(
2449 'Suggested missing target path OWNERS:\n %s' %
2450 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552451 return output_list
2452
2453 return []
2454
2455
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492456# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402457def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492458 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402459 black_list = (_EXCLUDED_PATHS +
2460 _TEST_CODE_EXCLUDED_PATHS +
2461 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042462 (r"^base[\\/]logging\.h$",
2463 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222464 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042465 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2466 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2467 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122468 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182469 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152470 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032471 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152472 r"^chrome[\\/]chrome_cleaner[\\/].*",
2473 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2474 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042475 r"^chromecast[\\/]",
2476 r"^cloud_print[\\/]",
2477 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482478 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042479 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312480 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042481 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462482 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042483 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462484 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042485 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252486 r"gl_helper_benchmark\.cc$",
Robert Flackc0ee0272020-02-26 05:57:402487 r"^content[\\/]renderer[\\/]render_frame_impl.cc$",
Egor Paskoce145c42018-09-28 19:31:042488 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2489 r"^courgette[\\/]courgette_tool\.cc$",
2490 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272491 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002492 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332493 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042494 r"^ipc[\\/]ipc_logging\.cc$",
2495 r"^native_client_sdk[\\/]",
2496 r"^remoting[\\/]base[\\/]logging\.h$",
2497 r"^remoting[\\/]host[\\/].*",
2498 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062499 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332500 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042501 r"^tools[\\/]",
2502 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2503 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332504 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402505 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492506 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402507
thomasanderson625d3932017-03-29 07:16:582508 log_info = set([])
2509 printf = set([])
[email protected]85218562013-11-22 07:41:402510
2511 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582512 for _, line in f.ChangedContents():
2513 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2514 log_info.add(f.LocalPath())
2515 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2516 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372517
thomasanderson625d3932017-03-29 07:16:582518 if input_api.re.search(r"\bprintf\(", line):
2519 printf.add(f.LocalPath())
2520 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2521 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402522
2523 if log_info:
2524 return [output_api.PresubmitError(
2525 'These files spam the console log with LOG(INFO):',
2526 items=log_info)]
2527 if printf:
2528 return [output_api.PresubmitError(
2529 'These files spam the console log with printf/fprintf:',
2530 items=printf)]
2531 return []
2532
2533
[email protected]49aa76a2013-12-04 06:59:162534def _CheckForAnonymousVariables(input_api, output_api):
2535 """These types are all expected to hold locks while in scope and
2536 so should never be anonymous (which causes them to be immediately
2537 destroyed)."""
2538 they_who_must_be_named = [
2539 'base::AutoLock',
2540 'base::AutoReset',
2541 'base::AutoUnlock',
2542 'SkAutoAlphaRestore',
2543 'SkAutoBitmapShaderInstall',
2544 'SkAutoBlitterChoose',
2545 'SkAutoBounderCommit',
2546 'SkAutoCallProc',
2547 'SkAutoCanvasRestore',
2548 'SkAutoCommentBlock',
2549 'SkAutoDescriptor',
2550 'SkAutoDisableDirectionCheck',
2551 'SkAutoDisableOvalCheck',
2552 'SkAutoFree',
2553 'SkAutoGlyphCache',
2554 'SkAutoHDC',
2555 'SkAutoLockColors',
2556 'SkAutoLockPixels',
2557 'SkAutoMalloc',
2558 'SkAutoMaskFreeImage',
2559 'SkAutoMutexAcquire',
2560 'SkAutoPathBoundsUpdate',
2561 'SkAutoPDFRelease',
2562 'SkAutoRasterClipValidate',
2563 'SkAutoRef',
2564 'SkAutoTime',
2565 'SkAutoTrace',
2566 'SkAutoUnref',
2567 ]
2568 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2569 # bad: base::AutoLock(lock.get());
2570 # not bad: base::AutoLock lock(lock.get());
2571 bad_pattern = input_api.re.compile(anonymous)
2572 # good: new base::AutoLock(lock.get())
2573 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2574 errors = []
2575
2576 for f in input_api.AffectedFiles():
2577 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2578 continue
2579 for linenum, line in f.ChangedContents():
2580 if bad_pattern.search(line) and not good_pattern.search(line):
2581 errors.append('%s:%d' % (f.LocalPath(), linenum))
2582
2583 if errors:
2584 return [output_api.PresubmitError(
2585 'These lines create anonymous variables that need to be named:',
2586 items=errors)]
2587 return []
2588
2589
Peter Kasting4844e46e2018-02-23 07:27:102590def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532591 # Returns whether |template_str| is of the form <T, U...> for some types T
2592 # and U. Assumes that |template_str| is already in the form <...>.
2593 def HasMoreThanOneArg(template_str):
2594 # Level of <...> nesting.
2595 nesting = 0
2596 for c in template_str:
2597 if c == '<':
2598 nesting += 1
2599 elif c == '>':
2600 nesting -= 1
2601 elif c == ',' and nesting == 1:
2602 return True
2603 return False
2604
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492605 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102606 sources = lambda affected_file: input_api.FilterSourceFile(
2607 affected_file,
2608 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2609 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492610 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552611
2612 # Pattern to capture a single "<...>" block of template arguments. It can
2613 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2614 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2615 # latter would likely require counting that < and > match, which is not
2616 # expressible in regular languages. Should the need arise, one can introduce
2617 # limited counting (matching up to a total number of nesting depth), which
2618 # should cover all practical cases for already a low nesting limit.
2619 template_arg_pattern = (
2620 r'<[^>]*' # Opening block of <.
2621 r'>([^<]*>)?') # Closing block of >.
2622 # Prefix expressing that whatever follows is not already inside a <...>
2623 # block.
2624 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102625 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552626 not_inside_template_arg_pattern
2627 + r'\bstd::unique_ptr'
2628 + template_arg_pattern
2629 + r'\(\)')
2630
2631 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2632 template_arg_no_array_pattern = (
2633 r'<[^>]*[^]]' # Opening block of <.
2634 r'>([^(<]*[^]]>)?') # Closing block of >.
2635 # Prefix saying that what follows is the start of an expression.
2636 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2637 # Suffix saying that what follows are call parentheses with a non-empty list
2638 # of arguments.
2639 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532640 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552641 return_construct_pattern = input_api.re.compile(
2642 start_of_expr_pattern
2643 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532644 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552645 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532646 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552647 + nonempty_arg_list_pattern)
2648
Vaclav Brozek851d9602018-04-04 16:13:052649 problems_constructor = []
2650 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102651 for f in input_api.AffectedSourceFiles(sources):
2652 for line_number, line in f.ChangedContents():
2653 # Disallow:
2654 # return std::unique_ptr<T>(foo);
2655 # bar = std::unique_ptr<T>(foo);
2656 # But allow:
2657 # return std::unique_ptr<T[]>(foo);
2658 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532659 # And also allow cases when the second template argument is present. Those
2660 # cases cannot be handled by std::make_unique:
2661 # return std::unique_ptr<T, U>(foo);
2662 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052663 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532664 return_construct_result = return_construct_pattern.search(line)
2665 if return_construct_result and not HasMoreThanOneArg(
2666 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052667 problems_constructor.append(
2668 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102669 # Disallow:
2670 # std::unique_ptr<T>()
2671 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052672 problems_nullptr.append(
2673 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2674
2675 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162676 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052677 errors.append(output_api.PresubmitError(
2678 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162679 problems_nullptr))
2680 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052681 errors.append(output_api.PresubmitError(
2682 'The following files use explicit std::unique_ptr constructor.'
2683 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162684 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102685 return errors
2686
2687
[email protected]999261d2014-03-03 20:08:082688def _CheckUserActionUpdate(input_api, output_api):
2689 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522690 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082691 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522692 # If actions.xml is already included in the changelist, the PRESUBMIT
2693 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082694 return []
2695
[email protected]999261d2014-03-03 20:08:082696 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2697 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522698 current_actions = None
[email protected]999261d2014-03-03 20:08:082699 for f in input_api.AffectedFiles(file_filter=file_filter):
2700 for line_num, line in f.ChangedContents():
2701 match = input_api.re.search(action_re, line)
2702 if match:
[email protected]2f92dec2014-03-07 19:21:522703 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2704 # loaded only once.
2705 if not current_actions:
2706 with open('tools/metrics/actions/actions.xml') as actions_f:
2707 current_actions = actions_f.read()
2708 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082709 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522710 action = 'name="{0}"'.format(action_name)
2711 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082712 return [output_api.PresubmitPromptWarning(
2713 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522714 'tools/metrics/actions/actions.xml. Please run '
2715 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082716 % (f.LocalPath(), line_num, action_name))]
2717 return []
2718
2719
Daniel Cheng13ca61a882017-08-25 15:11:252720def _ImportJSONCommentEater(input_api):
2721 import sys
2722 sys.path = sys.path + [input_api.os_path.join(
2723 input_api.PresubmitLocalPath(),
2724 'tools', 'json_comment_eater')]
2725 import json_comment_eater
2726 return json_comment_eater
2727
2728
[email protected]99171a92014-06-03 08:44:472729def _GetJSONParseError(input_api, filename, eat_comments=True):
2730 try:
2731 contents = input_api.ReadFile(filename)
2732 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252733 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132734 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472735
2736 input_api.json.loads(contents)
2737 except ValueError as e:
2738 return e
2739 return None
2740
2741
2742def _GetIDLParseError(input_api, filename):
2743 try:
2744 contents = input_api.ReadFile(filename)
2745 idl_schema = input_api.os_path.join(
2746 input_api.PresubmitLocalPath(),
2747 'tools', 'json_schema_compiler', 'idl_schema.py')
2748 process = input_api.subprocess.Popen(
2749 [input_api.python_executable, idl_schema],
2750 stdin=input_api.subprocess.PIPE,
2751 stdout=input_api.subprocess.PIPE,
2752 stderr=input_api.subprocess.PIPE,
2753 universal_newlines=True)
2754 (_, error) = process.communicate(input=contents)
2755 return error or None
2756 except ValueError as e:
2757 return e
2758
2759
2760def _CheckParseErrors(input_api, output_api):
2761 """Check that IDL and JSON files do not contain syntax errors."""
2762 actions = {
2763 '.idl': _GetIDLParseError,
2764 '.json': _GetJSONParseError,
2765 }
[email protected]99171a92014-06-03 08:44:472766 # Most JSON files are preprocessed and support comments, but these do not.
2767 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042768 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472769 ]
2770 # Only run IDL checker on files in these directories.
2771 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042772 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2773 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472774 ]
2775
2776 def get_action(affected_file):
2777 filename = affected_file.LocalPath()
2778 return actions.get(input_api.os_path.splitext(filename)[1])
2779
[email protected]99171a92014-06-03 08:44:472780 def FilterFile(affected_file):
2781 action = get_action(affected_file)
2782 if not action:
2783 return False
2784 path = affected_file.LocalPath()
2785
Sean Kau46e29bc2017-08-28 16:31:162786 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472787 return False
2788
2789 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162790 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472791 return False
2792 return True
2793
2794 results = []
2795 for affected_file in input_api.AffectedFiles(
2796 file_filter=FilterFile, include_deletes=False):
2797 action = get_action(affected_file)
2798 kwargs = {}
2799 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162800 _MatchesFile(input_api, json_no_comments_patterns,
2801 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472802 kwargs['eat_comments'] = False
2803 parse_error = action(input_api,
2804 affected_file.AbsoluteLocalPath(),
2805 **kwargs)
2806 if parse_error:
2807 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2808 (affected_file.LocalPath(), parse_error)))
2809 return results
2810
2811
[email protected]760deea2013-12-10 19:33:492812def _CheckJavaStyle(input_api, output_api):
2813 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472814 import sys
[email protected]760deea2013-12-10 19:33:492815 original_sys_path = sys.path
2816 try:
2817 sys.path = sys.path + [input_api.os_path.join(
2818 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2819 import checkstyle
2820 finally:
2821 # Restore sys.path to what it was before.
2822 sys.path = original_sys_path
2823
2824 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092825 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512826 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492827
2828
Nate Fischerdfd9812e2019-07-18 22:03:002829def _CheckPythonDevilInit(input_api, output_api):
2830 """Checks to make sure devil is initialized correctly in python scripts."""
2831 script_common_initialize_pattern = input_api.re.compile(
2832 r'script_common\.InitializeEnvironment\(')
2833 devil_env_config_initialize = input_api.re.compile(
2834 r'devil_env\.config\.Initialize\(')
2835
2836 errors = []
2837
2838 sources = lambda affected_file: input_api.FilterSourceFile(
2839 affected_file,
2840 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2841 (r'^build[\\/]android[\\/]devil_chromium\.py',
2842 r'^third_party[\\/].*',)),
2843 white_list=[r'.*\.py$'])
2844
2845 for f in input_api.AffectedSourceFiles(sources):
2846 for line_num, line in f.ChangedContents():
2847 if (script_common_initialize_pattern.search(line) or
2848 devil_env_config_initialize.search(line)):
2849 errors.append("%s:%d" % (f.LocalPath(), line_num))
2850
2851 results = []
2852
2853 if errors:
2854 results.append(output_api.PresubmitError(
2855 'Devil initialization should always be done using '
2856 'devil_chromium.Initialize() in the chromium project, to use better '
2857 'defaults for dependencies (ex. up-to-date version of adb).',
2858 errors))
2859
2860 return results
2861
2862
Sean Kau46e29bc2017-08-28 16:31:162863def _MatchesFile(input_api, patterns, path):
2864 for pattern in patterns:
2865 if input_api.re.search(pattern, path):
2866 return True
2867 return False
2868
2869
Daniel Cheng7052cdf2017-11-21 19:23:292870def _GetOwnersFilesToCheckForIpcOwners(input_api):
2871 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172872
Daniel Cheng7052cdf2017-11-21 19:23:292873 Returns:
2874 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2875 contain to cover IPC-related files with noparent reviewer rules.
2876 """
2877 # Whether or not a file affects IPC is (mostly) determined by a simple list
2878 # of filename patterns.
dchenge07de812016-06-20 19:27:172879 file_patterns = [
palmerb19a0932017-01-24 04:00:312880 # Legacy IPC:
dchenge07de812016-06-20 19:27:172881 '*_messages.cc',
2882 '*_messages*.h',
2883 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312884 # Mojo IPC:
dchenge07de812016-06-20 19:27:172885 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472886 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172887 '*_struct_traits*.*',
2888 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312889 '*.typemap',
2890 # Android native IPC:
2891 '*.aidl',
2892 # Blink uses a different file naming convention:
2893 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472894 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172895 '*StructTraits*.*',
2896 '*TypeConverter*.*',
2897 ]
2898
scottmg7a6ed5ba2016-11-04 18:22:042899 # These third_party directories do not contain IPCs, but contain files
2900 # matching the above patterns, which trigger false positives.
2901 exclude_paths = [
2902 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162903 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232904 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292905 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542906 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162907 # These files are just used to communicate between class loaders running
2908 # in the same process.
2909 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572910 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2911
scottmg7a6ed5ba2016-11-04 18:22:042912 ]
2913
dchenge07de812016-06-20 19:27:172914 # Dictionary mapping an OWNERS file path to Patterns.
2915 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2916 # rules ) to a PatternEntry.
2917 # PatternEntry is a dictionary with two keys:
2918 # - 'files': the files that are matched by this pattern
2919 # - 'rules': the per-file rules needed for this pattern
2920 # For example, if we expect OWNERS file to contain rules for *.mojom and
2921 # *_struct_traits*.*, Patterns might look like this:
2922 # {
2923 # '*.mojom': {
2924 # 'files': ...,
2925 # 'rules': [
2926 # 'per-file *.mojom=set noparent',
2927 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2928 # ],
2929 # },
2930 # '*_struct_traits*.*': {
2931 # 'files': ...,
2932 # 'rules': [
2933 # 'per-file *_struct_traits*.*=set noparent',
2934 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2935 # ],
2936 # },
2937 # }
2938 to_check = {}
2939
Daniel Cheng13ca61a882017-08-25 15:11:252940 def AddPatternToCheck(input_file, pattern):
2941 owners_file = input_api.os_path.join(
2942 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2943 if owners_file not in to_check:
2944 to_check[owners_file] = {}
2945 if pattern not in to_check[owners_file]:
2946 to_check[owners_file][pattern] = {
2947 'files': [],
2948 'rules': [
2949 'per-file %s=set noparent' % pattern,
2950 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2951 ]
2952 }
Vaclav Brozekd5de76a2018-03-17 07:57:502953 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252954
dchenge07de812016-06-20 19:27:172955 # Iterate through the affected files to see what we actually need to check
2956 # for. We should only nag patch authors about per-file rules if a file in that
2957 # directory would match that pattern. If a directory only contains *.mojom
2958 # files and no *_messages*.h files, we should only nag about rules for
2959 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252960 for f in input_api.AffectedFiles(include_deletes=False):
2961 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362962 # affected files for .json, .cc, and .h files which look like they contain
2963 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162964 if (f.LocalPath().endswith('.json') and
2965 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2966 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252967 json_comment_eater = _ImportJSONCommentEater(input_api)
2968 mostly_json_lines = '\n'.join(f.NewContents())
2969 # Comments aren't allowed in strict JSON, so filter them out.
2970 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432971 try:
2972 json_content = input_api.json.loads(json_lines)
2973 except:
2974 # There's another PRESUBMIT check that already verifies that JSON files
2975 # are not invalid, so no need to emit another warning here.
2976 continue
Daniel Cheng13ca61a882017-08-25 15:11:252977 if 'interface_provider_specs' in json_content:
2978 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362979 else:
2980 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2981 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2982 if (manifest_pattern.search(f.LocalPath()) and not
2983 test_manifest_pattern.search(f.LocalPath())):
2984 # We expect all actual service manifest files to contain at least one
2985 # qualified reference to service_manager::Manifest.
2986 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2987 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172988 for pattern in file_patterns:
2989 if input_api.fnmatch.fnmatch(
2990 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042991 skip = False
2992 for exclude in exclude_paths:
2993 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2994 skip = True
2995 break
2996 if skip:
2997 continue
Daniel Cheng13ca61a882017-08-25 15:11:252998 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172999 break
3000
Daniel Cheng7052cdf2017-11-21 19:23:293001 return to_check
3002
3003
3004def _CheckIpcOwners(input_api, output_api):
3005 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3006 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
3007
3008 if to_check:
3009 # If there are any OWNERS files to check, there are IPC-related changes in
3010 # this CL. Auto-CC the review list.
3011 output_api.AppendCC('[email protected]')
3012
3013 # Go through the OWNERS files to check, filtering out rules that are already
3014 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173015 for owners_file, patterns in to_check.iteritems():
3016 try:
3017 with file(owners_file) as f:
3018 lines = set(f.read().splitlines())
3019 for entry in patterns.itervalues():
3020 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3021 ]
3022 except IOError:
3023 # No OWNERS file, so all the rules are definitely missing.
3024 continue
3025
3026 # All the remaining lines weren't found in OWNERS files, so emit an error.
3027 errors = []
3028 for owners_file, patterns in to_check.iteritems():
3029 missing_lines = []
3030 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503031 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173032 missing_lines.extend(entry['rules'])
3033 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3034 if missing_lines:
3035 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053036 'Because of the presence of files:\n%s\n\n'
3037 '%s needs the following %d lines added:\n\n%s' %
3038 ('\n'.join(files), owners_file, len(missing_lines),
3039 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173040
3041 results = []
3042 if errors:
vabrf5ce3bf92016-07-11 14:52:413043 if input_api.is_committing:
3044 output = output_api.PresubmitError
3045 else:
3046 output = output_api.PresubmitPromptWarning
3047 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593048 'Found OWNERS files that need to be updated for IPC security ' +
3049 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173050 long_text='\n\n'.join(errors)))
3051
3052 return results
3053
3054
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263055def _CheckSetNoParent(input_api, output_api):
3056 """Checks that set noparent is only used together with an OWNERS file in
3057 //build/OWNERS.setnoparent (see also
3058 //docs/code_reviews.md#owners-files-details)
3059 """
3060 errors = []
3061
3062 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3063 allowed_owners_files = set()
3064 with open(allowed_owners_files_file, 'r') as f:
3065 for line in f:
3066 line = line.strip()
3067 if not line or line.startswith('#'):
3068 continue
3069 allowed_owners_files.add(line)
3070
3071 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3072
3073 for f in input_api.AffectedFiles(include_deletes=False):
3074 if not f.LocalPath().endswith('OWNERS'):
3075 continue
3076
3077 found_owners_files = set()
3078 found_set_noparent_lines = dict()
3079
3080 # Parse the OWNERS file.
3081 for lineno, line in enumerate(f.NewContents(), 1):
3082 line = line.strip()
3083 if line.startswith('set noparent'):
3084 found_set_noparent_lines[''] = lineno
3085 if line.startswith('file://'):
3086 if line in allowed_owners_files:
3087 found_owners_files.add('')
3088 if line.startswith('per-file'):
3089 match = per_file_pattern.match(line)
3090 if match:
3091 glob = match.group(1).strip()
3092 directive = match.group(2).strip()
3093 if directive == 'set noparent':
3094 found_set_noparent_lines[glob] = lineno
3095 if directive.startswith('file://'):
3096 if directive in allowed_owners_files:
3097 found_owners_files.add(glob)
3098
3099 # Check that every set noparent line has a corresponding file:// line
3100 # listed in build/OWNERS.setnoparent.
3101 for set_noparent_line in found_set_noparent_lines:
3102 if set_noparent_line in found_owners_files:
3103 continue
3104 errors.append(' %s:%d' % (f.LocalPath(),
3105 found_set_noparent_lines[set_noparent_line]))
3106
3107 results = []
3108 if errors:
3109 if input_api.is_committing:
3110 output = output_api.PresubmitError
3111 else:
3112 output = output_api.PresubmitPromptWarning
3113 results.append(output(
3114 'Found the following "set noparent" restrictions in OWNERS files that '
3115 'do not include owners from build/OWNERS.setnoparent:',
3116 long_text='\n\n'.join(errors)))
3117 return results
3118
3119
jbriance9e12f162016-11-25 07:57:503120def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313121 """Checks that added or removed lines in non third party affected
3122 header files do not lead to new useless class or struct forward
3123 declaration.
jbriance9e12f162016-11-25 07:57:503124 """
3125 results = []
3126 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3127 input_api.re.MULTILINE)
3128 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3129 input_api.re.MULTILINE)
3130 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313131 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193132 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493133 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313134 continue
3135
jbriance9e12f162016-11-25 07:57:503136 if not f.LocalPath().endswith('.h'):
3137 continue
3138
3139 contents = input_api.ReadFile(f)
3140 fwd_decls = input_api.re.findall(class_pattern, contents)
3141 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3142
3143 useless_fwd_decls = []
3144 for decl in fwd_decls:
3145 count = sum(1 for _ in input_api.re.finditer(
3146 r'\b%s\b' % input_api.re.escape(decl), contents))
3147 if count == 1:
3148 useless_fwd_decls.append(decl)
3149
3150 if not useless_fwd_decls:
3151 continue
3152
3153 for line in f.GenerateScmDiff().splitlines():
3154 if (line.startswith('-') and not line.startswith('--') or
3155 line.startswith('+') and not line.startswith('++')):
3156 for decl in useless_fwd_decls:
3157 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3158 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243159 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503160 (f.LocalPath(), decl)))
3161 useless_fwd_decls.remove(decl)
3162
3163 return results
3164
Jinsong Fan91ebbbd2019-04-16 14:57:173165def _CheckAndroidDebuggableBuild(input_api, output_api):
3166 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3167 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3168 this is a debuggable build of Android.
3169 """
3170 build_type_check_pattern = input_api.re.compile(
3171 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3172
3173 errors = []
3174
3175 sources = lambda affected_file: input_api.FilterSourceFile(
3176 affected_file,
3177 black_list=(_EXCLUDED_PATHS +
3178 _TEST_CODE_EXCLUDED_PATHS +
3179 input_api.DEFAULT_BLACK_LIST +
3180 (r"^android_webview[\\/]support_library[\\/]"
3181 "boundary_interfaces[\\/]",
3182 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3183 r'^third_party[\\/].*',
3184 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3185 r"webview[\\/]chromium[\\/]License.*",)),
3186 white_list=[r'.*\.java$'])
3187
3188 for f in input_api.AffectedSourceFiles(sources):
3189 for line_num, line in f.ChangedContents():
3190 if build_type_check_pattern.search(line):
3191 errors.append("%s:%d" % (f.LocalPath(), line_num))
3192
3193 results = []
3194
3195 if errors:
3196 results.append(output_api.PresubmitPromptWarning(
3197 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3198 ' Please use BuildInfo.isDebugAndroid() instead.',
3199 errors))
3200
3201 return results
jbriance9e12f162016-11-25 07:57:503202
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493203# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293204def _CheckAndroidToastUsage(input_api, output_api):
3205 """Checks that code uses org.chromium.ui.widget.Toast instead of
3206 android.widget.Toast (Chromium Toast doesn't force hardware
3207 acceleration on low-end devices, saving memory).
3208 """
3209 toast_import_pattern = input_api.re.compile(
3210 r'^import android\.widget\.Toast;$')
3211
3212 errors = []
3213
3214 sources = lambda affected_file: input_api.FilterSourceFile(
3215 affected_file,
3216 black_list=(_EXCLUDED_PATHS +
3217 _TEST_CODE_EXCLUDED_PATHS +
3218 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043219 (r'^chromecast[\\/].*',
3220 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493221 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293222
3223 for f in input_api.AffectedSourceFiles(sources):
3224 for line_num, line in f.ChangedContents():
3225 if toast_import_pattern.search(line):
3226 errors.append("%s:%d" % (f.LocalPath(), line_num))
3227
3228 results = []
3229
3230 if errors:
3231 results.append(output_api.PresubmitError(
3232 'android.widget.Toast usage is detected. Android toasts use hardware'
3233 ' acceleration, and can be\ncostly on low-end devices. Please use'
3234 ' org.chromium.ui.widget.Toast instead.\n'
3235 'Contact [email protected] if you have any questions.',
3236 errors))
3237
3238 return results
3239
3240
dgnaa68d5e2015-06-10 10:08:223241def _CheckAndroidCrLogUsage(input_api, output_api):
3242 """Checks that new logs using org.chromium.base.Log:
3243 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513244 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223245 """
pkotwicza1dd0b002016-05-16 14:41:043246
torne89540622017-03-24 19:41:303247 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043248 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303249 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043250 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303251 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043252 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3253 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093254 # The customtabs_benchmark is a small app that does not depend on Chromium
3255 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043256 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043257 ]
3258
dgnaa68d5e2015-06-10 10:08:223259 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123260 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3261 class_in_base_pattern = input_api.re.compile(
3262 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3263 has_some_log_import_pattern = input_api.re.compile(
3264 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223265 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123266 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223267 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463268 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223269
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463270 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493271 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043272 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123273
dgnaa68d5e2015-06-10 10:08:223274 tag_decl_errors = []
3275 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123276 tag_errors = []
dgn38736db2015-09-18 19:20:513277 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123278 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223279
3280 for f in input_api.AffectedSourceFiles(sources):
3281 file_content = input_api.ReadFile(f)
3282 has_modified_logs = False
3283
3284 # Per line checks
dgn87d9fb62015-06-12 09:15:123285 if (cr_log_import_pattern.search(file_content) or
3286 (class_in_base_pattern.search(file_content) and
3287 not has_some_log_import_pattern.search(file_content))):
3288 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223289 for line_num, line in f.ChangedContents():
3290
3291 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123292 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223293 if match:
3294 has_modified_logs = True
3295
3296 # Make sure it uses "TAG"
3297 if not match.group('tag') == 'TAG':
3298 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123299 else:
3300 # Report non cr Log function calls in changed lines
3301 for line_num, line in f.ChangedContents():
3302 if log_call_pattern.search(line):
3303 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223304
3305 # Per file checks
3306 if has_modified_logs:
3307 # Make sure the tag is using the "cr" prefix and is not too long
3308 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513309 tag_name = match.group('name') if match else None
3310 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223311 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513312 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223313 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513314 elif '.' in tag_name:
3315 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223316
3317 results = []
3318 if tag_decl_errors:
3319 results.append(output_api.PresubmitPromptWarning(
3320 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513321 '"private static final String TAG = "<package tag>".\n'
3322 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223323 tag_decl_errors))
3324
3325 if tag_length_errors:
3326 results.append(output_api.PresubmitError(
3327 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513328 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223329 tag_length_errors))
3330
3331 if tag_errors:
3332 results.append(output_api.PresubmitPromptWarning(
3333 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3334 tag_errors))
3335
dgn87d9fb62015-06-12 09:15:123336 if util_log_errors:
dgn4401aa52015-04-29 16:26:173337 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123338 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3339 util_log_errors))
3340
dgn38736db2015-09-18 19:20:513341 if tag_with_dot_errors:
3342 results.append(output_api.PresubmitPromptWarning(
3343 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3344 tag_with_dot_errors))
3345
dgn4401aa52015-04-29 16:26:173346 return results
3347
3348
Yoland Yanb92fa522017-08-28 17:37:063349def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3350 """Checks that junit.framework.* is no longer used."""
3351 deprecated_junit_framework_pattern = input_api.re.compile(
3352 r'^import junit\.framework\..*;',
3353 input_api.re.MULTILINE)
3354 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493355 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063356 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133357 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063358 for line_num, line in f.ChangedContents():
3359 if deprecated_junit_framework_pattern.search(line):
3360 errors.append("%s:%d" % (f.LocalPath(), line_num))
3361
3362 results = []
3363 if errors:
3364 results.append(output_api.PresubmitError(
3365 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3366 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3367 ' if you have any question.', errors))
3368 return results
3369
3370
3371def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3372 """Checks that if new Java test classes have inheritance.
3373 Either the new test class is JUnit3 test or it is a JUnit4 test class
3374 with a base class, either case is undesirable.
3375 """
3376 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3377
3378 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493379 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063380 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133381 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063382 if not f.OldContents():
3383 class_declaration_start_flag = False
3384 for line_num, line in f.ChangedContents():
3385 if class_declaration_pattern.search(line):
3386 class_declaration_start_flag = True
3387 if class_declaration_start_flag and ' extends ' in line:
3388 errors.append('%s:%d' % (f.LocalPath(), line_num))
3389 if '{' in line:
3390 class_declaration_start_flag = False
3391
3392 results = []
3393 if errors:
3394 results.append(output_api.PresubmitPromptWarning(
3395 'The newly created files include Test classes that inherits from base'
3396 ' class. Please do not use inheritance in JUnit4 tests or add new'
3397 ' JUnit3 tests. Contact [email protected] if you have any'
3398 ' questions.', errors))
3399 return results
3400
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203401
yolandyan45001472016-12-21 21:12:423402def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3403 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3404 deprecated_annotation_import_pattern = input_api.re.compile(
3405 r'^import android\.test\.suitebuilder\.annotation\..*;',
3406 input_api.re.MULTILINE)
3407 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493408 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423409 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133410 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423411 for line_num, line in f.ChangedContents():
3412 if deprecated_annotation_import_pattern.search(line):
3413 errors.append("%s:%d" % (f.LocalPath(), line_num))
3414
3415 results = []
3416 if errors:
3417 results.append(output_api.PresubmitError(
3418 'Annotations in android.test.suitebuilder.annotation have been'
3419 ' deprecated since API level 24. Please use android.support.test.filters'
3420 ' from //third_party/android_support_test_runner:runner_java instead.'
3421 ' Contact [email protected] if you have any questions.', errors))
3422 return results
3423
3424
agrieve7b6479d82015-10-07 14:24:223425def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3426 """Checks if MDPI assets are placed in a correct directory."""
3427 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3428 ('/res/drawable/' in f.LocalPath() or
3429 '/res/drawable-ldrtl/' in f.LocalPath()))
3430 errors = []
3431 for f in input_api.AffectedFiles(include_deletes=False,
3432 file_filter=file_filter):
3433 errors.append(' %s' % f.LocalPath())
3434
3435 results = []
3436 if errors:
3437 results.append(output_api.PresubmitError(
3438 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3439 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3440 '/res/drawable-ldrtl/.\n'
3441 'Contact [email protected] if you have questions.', errors))
3442 return results
3443
3444
Nate Fischer535972b2017-09-16 01:06:183445def _CheckAndroidWebkitImports(input_api, output_api):
3446 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353447 android.webview.ValueCallback except in the WebView glue layer
3448 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183449 """
3450 valuecallback_import_pattern = input_api.re.compile(
3451 r'^import android\.webkit\.ValueCallback;$')
3452
3453 errors = []
3454
3455 sources = lambda affected_file: input_api.FilterSourceFile(
3456 affected_file,
3457 black_list=(_EXCLUDED_PATHS +
3458 _TEST_CODE_EXCLUDED_PATHS +
3459 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353460 (r'^android_webview[\\/]glue[\\/].*',
3461 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493462 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183463
3464 for f in input_api.AffectedSourceFiles(sources):
3465 for line_num, line in f.ChangedContents():
3466 if valuecallback_import_pattern.search(line):
3467 errors.append("%s:%d" % (f.LocalPath(), line_num))
3468
3469 results = []
3470
3471 if errors:
3472 results.append(output_api.PresubmitError(
3473 'android.webkit.ValueCallback usage is detected outside of the glue'
3474 ' layer. To stay compatible with the support library, android.webkit.*'
3475 ' classes should only be used inside the glue layer and'
3476 ' org.chromium.base.Callback should be used instead.',
3477 errors))
3478
3479 return results
3480
3481
Becky Zhou7c69b50992018-12-10 19:37:573482def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3483 """Checks Android XML styles """
3484 import sys
3485 original_sys_path = sys.path
3486 try:
3487 sys.path = sys.path + [input_api.os_path.join(
3488 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3489 import checkxmlstyle
3490 finally:
3491 # Restore sys.path to what it was before.
3492 sys.path = original_sys_path
3493
3494 if is_check_on_upload:
3495 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3496 else:
3497 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3498
3499
agrievef32bcc72016-04-04 14:57:403500class PydepsChecker(object):
3501 def __init__(self, input_api, pydeps_files):
3502 self._file_cache = {}
3503 self._input_api = input_api
3504 self._pydeps_files = pydeps_files
3505
3506 def _LoadFile(self, path):
3507 """Returns the list of paths within a .pydeps file relative to //."""
3508 if path not in self._file_cache:
3509 with open(path) as f:
3510 self._file_cache[path] = f.read()
3511 return self._file_cache[path]
3512
3513 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3514 """Returns an interable of paths within the .pydep, relativized to //."""
3515 os_path = self._input_api.os_path
3516 pydeps_dir = os_path.dirname(pydeps_path)
3517 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3518 if not l.startswith('*'))
3519 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3520
3521 def _CreateFilesToPydepsMap(self):
3522 """Returns a map of local_path -> list_of_pydeps."""
3523 ret = {}
3524 for pydep_local_path in self._pydeps_files:
3525 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3526 ret.setdefault(path, []).append(pydep_local_path)
3527 return ret
3528
3529 def ComputeAffectedPydeps(self):
3530 """Returns an iterable of .pydeps files that might need regenerating."""
3531 affected_pydeps = set()
3532 file_to_pydeps_map = None
3533 for f in self._input_api.AffectedFiles(include_deletes=True):
3534 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463535 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3536 # subrepositories. We can't figure out which files change, so re-check
3537 # all files.
3538 # Changes to print_python_deps.py affect all .pydeps.
3539 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403540 return self._pydeps_files
3541 elif local_path.endswith('.pydeps'):
3542 if local_path in self._pydeps_files:
3543 affected_pydeps.add(local_path)
3544 elif local_path.endswith('.py'):
3545 if file_to_pydeps_map is None:
3546 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3547 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3548 return affected_pydeps
3549
3550 def DetermineIfStale(self, pydeps_path):
3551 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413552 import difflib
John Budorick47ca3fe2018-02-10 00:53:103553 import os
3554
agrievef32bcc72016-04-04 14:57:403555 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3556 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103557 env = dict(os.environ)
3558 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403559 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103560 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413561 old_contents = old_pydeps_data[2:]
3562 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403563 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413564 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403565
3566
Tibor Goldschwendt360793f72019-06-25 18:23:493567def _ParseGclientArgs():
3568 args = {}
3569 with open('build/config/gclient_args.gni', 'r') as f:
3570 for line in f:
3571 line = line.strip()
3572 if not line or line.startswith('#'):
3573 continue
3574 attribute, value = line.split('=')
3575 args[attribute.strip()] = value.strip()
3576 return args
3577
3578
agrievef32bcc72016-04-04 14:57:403579def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3580 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403581 # This check is for Python dependency lists (.pydeps files), and involves
3582 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3583 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283584 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003585 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493586 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403587 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3588 results = []
3589 # First, check for new / deleted .pydeps.
3590 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033591 # Check whether we are running the presubmit check for a file in src.
3592 # f.LocalPath is relative to repo (src, or internal repo).
3593 # os_path.exists is relative to src repo.
3594 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3595 # to src and we can conclude that the pydeps is in src.
3596 if input_api.os_path.exists(f.LocalPath()):
3597 if f.LocalPath().endswith('.pydeps'):
3598 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3599 results.append(output_api.PresubmitError(
3600 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3601 'remove %s' % f.LocalPath()))
3602 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3603 results.append(output_api.PresubmitError(
3604 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3605 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403606
3607 if results:
3608 return results
3609
3610 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3611
3612 for pydep_path in checker.ComputeAffectedPydeps():
3613 try:
phajdan.jr0d9878552016-11-04 10:49:413614 result = checker.DetermineIfStale(pydep_path)
3615 if result:
3616 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403617 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413618 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3619 'To regenerate, run:\n\n %s' %
3620 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403621 except input_api.subprocess.CalledProcessError as error:
3622 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3623 long_text=error.output)]
3624
3625 return results
3626
3627
glidere61efad2015-02-18 17:39:433628def _CheckSingletonInHeaders(input_api, output_api):
3629 """Checks to make sure no header files have |Singleton<|."""
3630 def FileFilter(affected_file):
3631 # It's ok for base/memory/singleton.h to have |Singleton<|.
3632 black_list = (_EXCLUDED_PATHS +
3633 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043634 (r"^base[\\/]memory[\\/]singleton\.h$",
3635 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473636 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433637 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3638
sergeyu34d21222015-09-16 00:11:443639 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433640 files = []
3641 for f in input_api.AffectedSourceFiles(FileFilter):
3642 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3643 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3644 contents = input_api.ReadFile(f)
3645 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243646 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433647 pattern.search(line)):
3648 files.append(f)
3649 break
3650
3651 if files:
yolandyandaabc6d2016-04-18 18:29:393652 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443653 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433654 'Please move them to an appropriate source file so that the ' +
3655 'template gets instantiated in a single compilation unit.',
3656 files) ]
3657 return []
3658
3659
[email protected]fd20b902014-05-09 02:14:533660_DEPRECATED_CSS = [
3661 # Values
3662 ( "-webkit-box", "flex" ),
3663 ( "-webkit-inline-box", "inline-flex" ),
3664 ( "-webkit-flex", "flex" ),
3665 ( "-webkit-inline-flex", "inline-flex" ),
3666 ( "-webkit-min-content", "min-content" ),
3667 ( "-webkit-max-content", "max-content" ),
3668
3669 # Properties
3670 ( "-webkit-background-clip", "background-clip" ),
3671 ( "-webkit-background-origin", "background-origin" ),
3672 ( "-webkit-background-size", "background-size" ),
3673 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443674 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533675
3676 # Functions
3677 ( "-webkit-gradient", "gradient" ),
3678 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3679 ( "-webkit-linear-gradient", "linear-gradient" ),
3680 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3681 ( "-webkit-radial-gradient", "radial-gradient" ),
3682 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3683]
3684
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203685
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493686# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243687def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533688 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253689 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343690 documentation and iOS CSS for dom distiller
3691 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253692 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533693 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493694 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253695 black_list = (_EXCLUDED_PATHS +
3696 _TEST_CODE_EXCLUDED_PATHS +
3697 input_api.DEFAULT_BLACK_LIST +
3698 (r"^chrome/common/extensions/docs",
3699 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343700 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443701 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253702 r"^native_client_sdk"))
3703 file_filter = lambda f: input_api.FilterSourceFile(
3704 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533705 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3706 for line_num, line in fpath.ChangedContents():
3707 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023708 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533709 results.append(output_api.PresubmitError(
3710 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3711 (fpath.LocalPath(), line_num, deprecated_value, value)))
3712 return results
3713
mohan.reddyf21db962014-10-16 12:26:473714
rlanday6802cf632017-05-30 17:48:363715def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363716 bad_files = {}
3717 for f in input_api.AffectedFiles(include_deletes=False):
3718 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493719 not f.LocalPath().startswith('third_party/blink') and
3720 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363721 continue
3722
Daniel Bratell65b033262019-04-23 08:17:063723 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363724 continue
3725
Vaclav Brozekd5de76a2018-03-17 07:57:503726 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363727 if "#include" in line and "../" in line]
3728 if not relative_includes:
3729 continue
3730 bad_files[f.LocalPath()] = relative_includes
3731
3732 if not bad_files:
3733 return []
3734
3735 error_descriptions = []
3736 for file_path, bad_lines in bad_files.iteritems():
3737 error_description = file_path
3738 for line in bad_lines:
3739 error_description += '\n ' + line
3740 error_descriptions.append(error_description)
3741
3742 results = []
3743 results.append(output_api.PresubmitError(
3744 'You added one or more relative #include paths (including "../").\n'
3745 'These shouldn\'t be used because they can be used to include headers\n'
3746 'from code that\'s not correctly specified as a dependency in the\n'
3747 'relevant BUILD.gn file(s).',
3748 error_descriptions))
3749
3750 return results
3751
Takeshi Yoshinoe387aa32017-08-02 13:16:133752
Daniel Bratell65b033262019-04-23 08:17:063753def _CheckForCcIncludes(input_api, output_api):
3754 """Check that nobody tries to include a cc file. It's a relatively
3755 common error which results in duplicate symbols in object
3756 files. This may not always break the build until someone later gets
3757 very confusing linking errors."""
3758 results = []
3759 for f in input_api.AffectedFiles(include_deletes=False):
3760 # We let third_party code do whatever it wants
3761 if (f.LocalPath().startswith('third_party') and
3762 not f.LocalPath().startswith('third_party/blink') and
3763 not f.LocalPath().startswith('third_party\\blink')):
3764 continue
3765
3766 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3767 continue
3768
3769 for _, line in f.ChangedContents():
3770 if line.startswith('#include "'):
3771 included_file = line.split('"')[1]
3772 if _IsCPlusPlusFile(input_api, included_file):
3773 # The most common naming for external files with C++ code,
3774 # apart from standard headers, is to call them foo.inc, but
3775 # Chromium sometimes uses foo-inc.cc so allow that as well.
3776 if not included_file.endswith(('.h', '-inc.cc')):
3777 results.append(output_api.PresubmitError(
3778 'Only header files or .inc files should be included in other\n'
3779 'C++ files. Compiling the contents of a cc file more than once\n'
3780 'will cause duplicate information in the build which may later\n'
3781 'result in strange link_errors.\n' +
3782 f.LocalPath() + ':\n ' +
3783 line))
3784
3785 return results
3786
3787
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203788def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3789 if not isinstance(key, ast.Str):
3790 return 'Key at line %d must be a string literal' % key.lineno
3791 if not isinstance(value, ast.Dict):
3792 return 'Value at line %d must be a dict' % value.lineno
3793 if len(value.keys) != 1:
3794 return 'Dict at line %d must have single entry' % value.lineno
3795 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3796 return (
3797 'Entry at line %d must have a string literal \'filepath\' as key' %
3798 value.lineno)
3799 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133800
Takeshi Yoshinoe387aa32017-08-02 13:16:133801
Sergey Ulanov4af16052018-11-08 02:41:463802def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203803 if not isinstance(key, ast.Str):
3804 return 'Key at line %d must be a string literal' % key.lineno
3805 if not isinstance(value, ast.List):
3806 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463807 for element in value.elts:
3808 if not isinstance(element, ast.Str):
3809 return 'Watchlist elements on line %d is not a string' % key.lineno
3810 if not email_regex.match(element.s):
3811 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3812 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203813 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133814
Takeshi Yoshinoe387aa32017-08-02 13:16:133815
Sergey Ulanov4af16052018-11-08 02:41:463816def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203817 mismatch_template = (
3818 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3819 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133820
Sergey Ulanov4af16052018-11-08 02:41:463821 email_regex = input_api.re.compile(
3822 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3823
3824 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203825 i = 0
3826 last_key = ''
3827 while True:
3828 if i >= len(wd_dict.keys):
3829 if i >= len(w_dict.keys):
3830 return None
3831 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3832 elif i >= len(w_dict.keys):
3833 return (
3834 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133835
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203836 wd_key = wd_dict.keys[i]
3837 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133838
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203839 result = _CheckWatchlistDefinitionsEntrySyntax(
3840 wd_key, wd_dict.values[i], ast)
3841 if result is not None:
3842 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133843
Sergey Ulanov4af16052018-11-08 02:41:463844 result = _CheckWatchlistsEntrySyntax(
3845 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203846 if result is not None:
3847 return 'Bad entry in WATCHLISTS dict: %s' % result
3848
3849 if wd_key.s != w_key.s:
3850 return mismatch_template % (
3851 '%s at line %d' % (wd_key.s, wd_key.lineno),
3852 '%s at line %d' % (w_key.s, w_key.lineno))
3853
3854 if wd_key.s < last_key:
3855 return (
3856 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3857 (wd_key.lineno, w_key.lineno))
3858 last_key = wd_key.s
3859
3860 i = i + 1
3861
3862
Sergey Ulanov4af16052018-11-08 02:41:463863def _CheckWATCHLISTSSyntax(expression, input_api):
3864 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203865 if not isinstance(expression, ast.Expression):
3866 return 'WATCHLISTS file must contain a valid expression'
3867 dictionary = expression.body
3868 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3869 return 'WATCHLISTS file must have single dict with exactly two entries'
3870
3871 first_key = dictionary.keys[0]
3872 first_value = dictionary.values[0]
3873 second_key = dictionary.keys[1]
3874 second_value = dictionary.values[1]
3875
3876 if (not isinstance(first_key, ast.Str) or
3877 first_key.s != 'WATCHLIST_DEFINITIONS' or
3878 not isinstance(first_value, ast.Dict)):
3879 return (
3880 'The first entry of the dict in WATCHLISTS file must be '
3881 'WATCHLIST_DEFINITIONS dict')
3882
3883 if (not isinstance(second_key, ast.Str) or
3884 second_key.s != 'WATCHLISTS' or
3885 not isinstance(second_value, ast.Dict)):
3886 return (
3887 'The second entry of the dict in WATCHLISTS file must be '
3888 'WATCHLISTS dict')
3889
Sergey Ulanov4af16052018-11-08 02:41:463890 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133891
3892
3893def _CheckWATCHLISTS(input_api, output_api):
3894 for f in input_api.AffectedFiles(include_deletes=False):
3895 if f.LocalPath() == 'WATCHLISTS':
3896 contents = input_api.ReadFile(f, 'r')
3897
3898 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203899 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133900 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203901 # Get an AST tree for it and scan the tree for detailed style checking.
3902 expression = input_api.ast.parse(
3903 contents, filename='WATCHLISTS', mode='eval')
3904 except ValueError as e:
3905 return [output_api.PresubmitError(
3906 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3907 except SyntaxError as e:
3908 return [output_api.PresubmitError(
3909 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3910 except TypeError as e:
3911 return [output_api.PresubmitError(
3912 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133913
Sergey Ulanov4af16052018-11-08 02:41:463914 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203915 if result is not None:
3916 return [output_api.PresubmitError(result)]
3917 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133918
3919 return []
3920
3921
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193922def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3923 """Checks that newly added header files have corresponding GN changes.
3924 Note that this is only a heuristic. To be precise, run script:
3925 build/check_gn_headers.py.
3926 """
3927
3928 def headers(f):
3929 return input_api.FilterSourceFile(
3930 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3931
3932 new_headers = []
3933 for f in input_api.AffectedSourceFiles(headers):
3934 if f.Action() != 'A':
3935 continue
3936 new_headers.append(f.LocalPath())
3937
3938 def gn_files(f):
3939 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3940
3941 all_gn_changed_contents = ''
3942 for f in input_api.AffectedSourceFiles(gn_files):
3943 for _, line in f.ChangedContents():
3944 all_gn_changed_contents += line
3945
3946 problems = []
3947 for header in new_headers:
3948 basename = input_api.os_path.basename(header)
3949 if basename not in all_gn_changed_contents:
3950 problems.append(header)
3951
3952 if problems:
3953 return [output_api.PresubmitPromptWarning(
3954 'Missing GN changes for new header files', items=sorted(problems),
3955 long_text='Please double check whether newly added header files need '
3956 'corresponding changes in gn or gni files.\nThis checking is only a '
3957 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3958 'Read https://crbug.com/661774 for more info.')]
3959 return []
3960
3961
Michael Giuffridad3bc8672018-10-25 22:48:023962def _CheckCorrectProductNameInMessages(input_api, output_api):
3963 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3964
3965 This assumes we won't intentionally reference one product from the other
3966 product.
3967 """
3968 all_problems = []
3969 test_cases = [{
3970 "filename_postfix": "google_chrome_strings.grd",
3971 "correct_name": "Chrome",
3972 "incorrect_name": "Chromium",
3973 }, {
3974 "filename_postfix": "chromium_strings.grd",
3975 "correct_name": "Chromium",
3976 "incorrect_name": "Chrome",
3977 }]
3978
3979 for test_case in test_cases:
3980 problems = []
3981 filename_filter = lambda x: x.LocalPath().endswith(
3982 test_case["filename_postfix"])
3983
3984 # Check each new line. Can yield false positives in multiline comments, but
3985 # easier than trying to parse the XML because messages can have nested
3986 # children, and associating message elements with affected lines is hard.
3987 for f in input_api.AffectedSourceFiles(filename_filter):
3988 for line_num, line in f.ChangedContents():
3989 if "<message" in line or "<!--" in line or "-->" in line:
3990 continue
3991 if test_case["incorrect_name"] in line:
3992 problems.append(
3993 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3994
3995 if problems:
3996 message = (
3997 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3998 % (test_case["correct_name"], test_case["correct_name"],
3999 test_case["incorrect_name"]))
4000 all_problems.append(
4001 output_api.PresubmitPromptWarning(message, items=problems))
4002
4003 return all_problems
4004
4005
Dirk Pranke3c18a382019-03-15 01:07:514006def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4007 # TODO(crbug.com/941824): We need to make sure the entries in
4008 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4009 # so that users of //buildtools in other projects get the same tooling
4010 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4011 # support to gclient, we can eliminate the duplication and delete
4012 # this presubmit check.
4013
4014 # Update this regexp if new revisions are added to the files.
Ben Pastene81fa1222020-02-21 04:38:504015 # TODO(crbug.com/1054245): Remove the optional '_v2' bit.
4016 var_names = ['clang_format', 'libcxx', 'libcxxabi', 'libunwind']
Dirk Pranke3c18a382019-03-15 01:07:514017 rev_regexp = input_api.re.compile(
Ben Pastene81fa1222020-02-21 04:38:504018 "'((%s)_revision(?:_v2)?|gn_version)':" % '|'.join(var_names))
Dirk Pranke3c18a382019-03-15 01:07:514019
4020 # If a user is changing one revision, they need to change the same
4021 # line in both files. This means that any given change should contain
4022 # exactly the same list of changed lines that match the regexps. The
4023 # replace(' ', '') call allows us to ignore whitespace changes to the
4024 # lines. The 'long_text' parameter to the error will contain the
4025 # list of changed lines in both files, which should make it easy enough
4026 # to spot the error without going overboard in this implementation.
4027 revs_changes = {
4028 'DEPS': {},
4029 'buildtools/DEPS': {},
4030 }
4031 long_text = ''
4032
4033 for f in input_api.AffectedFiles(
4034 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4035 for line_num, line in f.ChangedContents():
4036 if rev_regexp.search(line):
4037 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4038 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4039
4040 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4041 return [output_api.PresubmitError(
4042 'Change buildtools revisions in sync in both //DEPS and '
4043 '//buildtools/DEPS.', long_text=long_text + '\n')]
4044 else:
4045 return []
4046
4047
Daniel Bratell93eb6c62019-04-29 20:13:364048def _CheckForTooLargeFiles(input_api, output_api):
4049 """Avoid large files, especially binary files, in the repository since
4050 git doesn't scale well for those. They will be in everyone's repo
4051 clones forever, forever making Chromium slower to clone and work
4052 with."""
4053
4054 # Uploading files to cloud storage is not trivial so we don't want
4055 # to set the limit too low, but the upper limit for "normal" large
4056 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4057 # anything over 20 MB is exceptional.
4058 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4059
4060 too_large_files = []
4061 for f in input_api.AffectedFiles():
4062 # Check both added and modified files (but not deleted files).
4063 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384064 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364065 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4066 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4067
4068 if too_large_files:
4069 message = (
4070 'Do not commit large files to git since git scales badly for those.\n' +
4071 'Instead put the large files in cloud storage and use DEPS to\n' +
4072 'fetch them.\n' + '\n'.join(too_large_files)
4073 )
4074 return [output_api.PresubmitError(
4075 'Too large files found in commit', long_text=message + '\n')]
4076 else:
4077 return []
4078
Max Morozb47503b2019-08-08 21:03:274079
4080def _CheckFuzzTargets(input_api, output_api):
4081 """Checks specific for fuzz target sources."""
4082 EXPORTED_SYMBOLS = [
4083 'LLVMFuzzerInitialize',
4084 'LLVMFuzzerCustomMutator',
4085 'LLVMFuzzerCustomCrossOver',
4086 'LLVMFuzzerMutate',
4087 ]
4088
4089 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4090
4091 def FilterFile(affected_file):
4092 """Ignore libFuzzer source code."""
4093 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4094 black_list = r"^third_party[\\/]libFuzzer"
4095
4096 return input_api.FilterSourceFile(
4097 affected_file,
4098 white_list=[white_list],
4099 black_list=[black_list])
4100
4101 files_with_missing_header = []
4102 for f in input_api.AffectedSourceFiles(FilterFile):
4103 contents = input_api.ReadFile(f, 'r')
4104 if REQUIRED_HEADER in contents:
4105 continue
4106
4107 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4108 files_with_missing_header.append(f.LocalPath())
4109
4110 if not files_with_missing_header:
4111 return []
4112
4113 long_text = (
4114 'If you define any of the libFuzzer optional functions (%s), it is '
4115 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4116 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4117 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4118 'to access command line arguments passed to the fuzzer. Instead, prefer '
4119 'static initialization and shared resources as documented in '
4120 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4121 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4122 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4123 )
4124
4125 return [output_api.PresubmitPromptWarning(
4126 message="Missing '%s' in:" % REQUIRED_HEADER,
4127 items=files_with_missing_header,
4128 long_text=long_text)]
4129
4130
Mohamed Heikald048240a2019-11-12 16:57:374131def _CheckNewImagesWarning(input_api, output_api):
4132 """
4133 Warns authors who add images into the repo to make sure their images are
4134 optimized before committing.
4135 """
4136 images_added = False
4137 image_paths = []
4138 errors = []
4139 filter_lambda = lambda x: input_api.FilterSourceFile(
4140 x,
4141 black_list=(('(?i).*test', r'.*\/junit\/')
4142 + input_api.DEFAULT_BLACK_LIST),
4143 white_list=[r'.*\/(drawable|mipmap)' ]
4144 )
4145 for f in input_api.AffectedFiles(
4146 include_deletes=False, file_filter=filter_lambda):
4147 local_path = f.LocalPath().lower()
4148 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4149 images_added = True
4150 image_paths.append(f)
4151 if images_added:
4152 errors.append(output_api.PresubmitPromptWarning(
4153 'It looks like you are trying to commit some images. If these are '
4154 'non-test-only images, please make sure to read and apply the tips in '
4155 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4156 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4157 'FYI only and will not block your CL on the CQ.', image_paths))
4158 return errors
4159
4160
dgnaa68d5e2015-06-10 10:08:224161def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574162 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224163 results = []
dgnaa68d5e2015-06-10 10:08:224164 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174165 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224166 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294167 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064168 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4169 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424170 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184171 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574172 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374173 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154174 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574175 return results
4176
4177def _AndroidSpecificOnCommitChecks(input_api, output_api):
4178 """Groups commit checks that target android code."""
4179 results = []
4180 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224181 return results
4182
4183
[email protected]22c9bd72011-03-27 16:47:394184def _CommonChecks(input_api, output_api):
4185 """Checks common to both upload and commit."""
4186 results = []
4187 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384188 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544189 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084190
4191 author = input_api.change.author_email
4192 if author and author not in _KNOWN_ROBOTS:
4193 results.extend(
4194 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4195
[email protected]55459852011-08-10 15:17:194196 results.extend(
[email protected]760deea2013-12-10 19:33:494197 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234198 results.extend(
4199 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544200 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184201 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344202 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524203 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224204 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444205 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594206 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314207 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064208 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124209 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184210 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224211 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304212 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494213 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034214 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494215 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444216 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294217 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274218 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074219 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544220 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444221 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394222 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554223 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044224 results.extend(
4225 input_api.canned_checks.CheckChangeHasNoTabs(
4226 input_api,
4227 output_api,
4228 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404229 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164230 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084231 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244232 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474233 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044234 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054235 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144236 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234237 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434238 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404239 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154240 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174241 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264242 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504243 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364244 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064245 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134246 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434247 results.extend(input_api.RunTests(
4248 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144249 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024250 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514251 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364252 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004253 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244254
Vaclav Brozekcdc7defb2018-03-20 09:54:354255 for f in input_api.AffectedFiles():
4256 path, name = input_api.os_path.split(f.LocalPath())
4257 if name == 'PRESUBMIT.py':
4258 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004259 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4260 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074261 # The PRESUBMIT.py file (and the directory containing it) might
4262 # have been affected by being moved or removed, so only try to
4263 # run the tests if they still exist.
4264 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4265 input_api, output_api, full_path,
4266 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394267 return results
[email protected]1f7b4172010-01-28 01:17:344268
[email protected]b337cb5b2011-01-23 21:24:054269
[email protected]b8079ae4a2012-12-05 19:56:494270def _CheckPatchFiles(input_api, output_api):
4271 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4272 if f.LocalPath().endswith(('.orig', '.rej'))]
4273 if problems:
4274 return [output_api.PresubmitError(
4275 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034276 else:
4277 return []
[email protected]b8079ae4a2012-12-05 19:56:494278
4279
Kent Tamura5a8755d2017-06-29 23:37:074280def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214281 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4282 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4283 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074284 include_re = input_api.re.compile(
4285 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4286 extension_re = input_api.re.compile(r'\.[a-z]+$')
4287 errors = []
4288 for f in input_api.AffectedFiles():
4289 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4290 continue
4291 found_line_number = None
4292 found_macro = None
4293 for line_num, line in f.ChangedContents():
4294 match = macro_re.search(line)
4295 if match:
4296 found_line_number = line_num
4297 found_macro = match.group(2)
4298 break
4299 if not found_line_number:
4300 continue
4301
4302 found_include = False
4303 for line in f.NewContents():
4304 if include_re.search(line):
4305 found_include = True
4306 break
4307 if found_include:
4308 continue
4309
4310 if not f.LocalPath().endswith('.h'):
4311 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4312 try:
4313 content = input_api.ReadFile(primary_header_path, 'r')
4314 if include_re.search(content):
4315 continue
4316 except IOError:
4317 pass
4318 errors.append('%s:%d %s macro is used without including build/'
4319 'build_config.h.'
4320 % (f.LocalPath(), found_line_number, found_macro))
4321 if errors:
4322 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4323 return []
4324
4325
[email protected]b00342e7f2013-03-26 16:21:544326def _DidYouMeanOSMacro(bad_macro):
4327 try:
4328 return {'A': 'OS_ANDROID',
4329 'B': 'OS_BSD',
4330 'C': 'OS_CHROMEOS',
4331 'F': 'OS_FREEBSD',
4332 'L': 'OS_LINUX',
4333 'M': 'OS_MACOSX',
4334 'N': 'OS_NACL',
4335 'O': 'OS_OPENBSD',
4336 'P': 'OS_POSIX',
4337 'S': 'OS_SOLARIS',
4338 'W': 'OS_WIN'}[bad_macro[3].upper()]
4339 except KeyError:
4340 return ''
4341
4342
4343def _CheckForInvalidOSMacrosInFile(input_api, f):
4344 """Check for sensible looking, totally invalid OS macros."""
4345 preprocessor_statement = input_api.re.compile(r'^\s*#')
4346 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4347 results = []
4348 for lnum, line in f.ChangedContents():
4349 if preprocessor_statement.search(line):
4350 for match in os_macro.finditer(line):
4351 if not match.group(1) in _VALID_OS_MACROS:
4352 good = _DidYouMeanOSMacro(match.group(1))
4353 did_you_mean = ' (did you mean %s?)' % good if good else ''
4354 results.append(' %s:%d %s%s' % (f.LocalPath(),
4355 lnum,
4356 match.group(1),
4357 did_you_mean))
4358 return results
4359
4360
4361def _CheckForInvalidOSMacros(input_api, output_api):
4362 """Check all affected files for invalid OS macros."""
4363 bad_macros = []
tzik3f295992018-12-04 20:32:234364 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474365 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544366 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4367
4368 if not bad_macros:
4369 return []
4370
4371 return [output_api.PresubmitError(
4372 'Possibly invalid OS macro[s] found. Please fix your code\n'
4373 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4374
lliabraa35bab3932014-10-01 12:16:444375
4376def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4377 """Check all affected files for invalid "if defined" macros."""
4378 ALWAYS_DEFINED_MACROS = (
4379 "TARGET_CPU_PPC",
4380 "TARGET_CPU_PPC64",
4381 "TARGET_CPU_68K",
4382 "TARGET_CPU_X86",
4383 "TARGET_CPU_ARM",
4384 "TARGET_CPU_MIPS",
4385 "TARGET_CPU_SPARC",
4386 "TARGET_CPU_ALPHA",
4387 "TARGET_IPHONE_SIMULATOR",
4388 "TARGET_OS_EMBEDDED",
4389 "TARGET_OS_IPHONE",
4390 "TARGET_OS_MAC",
4391 "TARGET_OS_UNIX",
4392 "TARGET_OS_WIN32",
4393 )
4394 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4395 results = []
4396 for lnum, line in f.ChangedContents():
4397 for match in ifdef_macro.finditer(line):
4398 if match.group(1) in ALWAYS_DEFINED_MACROS:
4399 always_defined = ' %s is always defined. ' % match.group(1)
4400 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4401 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4402 lnum,
4403 always_defined,
4404 did_you_mean))
4405 return results
4406
4407
4408def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4409 """Check all affected files for invalid "if defined" macros."""
4410 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054411 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444412 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054413 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214414 continue
lliabraa35bab3932014-10-01 12:16:444415 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4416 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4417
4418 if not bad_macros:
4419 return []
4420
4421 return [output_api.PresubmitError(
4422 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4423 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4424 bad_macros)]
4425
4426
mlamouria82272622014-09-16 18:45:044427def _CheckForIPCRules(input_api, output_api):
4428 """Check for same IPC rules described in
4429 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4430 """
4431 base_pattern = r'IPC_ENUM_TRAITS\('
4432 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4433 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4434
4435 problems = []
4436 for f in input_api.AffectedSourceFiles(None):
4437 local_path = f.LocalPath()
4438 if not local_path.endswith('.h'):
4439 continue
4440 for line_number, line in f.ChangedContents():
4441 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4442 problems.append(
4443 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4444
4445 if problems:
4446 return [output_api.PresubmitPromptWarning(
4447 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4448 else:
4449 return []
4450
[email protected]b00342e7f2013-03-26 16:21:544451
Stephen Martinis97a394142018-06-07 23:06:054452def _CheckForLongPathnames(input_api, output_api):
4453 """Check to make sure no files being submitted have long paths.
4454 This causes issues on Windows.
4455 """
4456 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194457 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054458 local_path = f.LocalPath()
4459 # Windows has a path limit of 260 characters. Limit path length to 200 so
4460 # that we have some extra for the prefix on dev machines and the bots.
4461 if len(local_path) > 200:
4462 problems.append(local_path)
4463
4464 if problems:
4465 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4466 else:
4467 return []
4468
4469
Daniel Bratell8ba52722018-03-02 16:06:144470def _CheckForIncludeGuards(input_api, output_api):
4471 """Check that header files have proper guards against multiple inclusion.
4472 If a file should not have such guards (and it probably should) then it
4473 should include the string "no-include-guard-because-multiply-included".
4474 """
Daniel Bratell6a75baef62018-06-04 10:04:454475 def is_chromium_header_file(f):
4476 # We only check header files under the control of the Chromium
4477 # project. That is, those outside third_party apart from
4478 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324479 # We also exclude *_message_generator.h headers as they use
4480 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454481 file_with_path = input_api.os_path.normpath(f.LocalPath())
4482 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324483 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454484 (not file_with_path.startswith('third_party') or
4485 file_with_path.startswith(
4486 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144487
4488 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344489 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144490
4491 errors = []
4492
Daniel Bratell6a75baef62018-06-04 10:04:454493 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144494 guard_name = None
4495 guard_line_number = None
4496 seen_guard_end = False
4497
4498 file_with_path = input_api.os_path.normpath(f.LocalPath())
4499 base_file_name = input_api.os_path.splitext(
4500 input_api.os_path.basename(file_with_path))[0]
4501 upper_base_file_name = base_file_name.upper()
4502
4503 expected_guard = replace_special_with_underscore(
4504 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144505
4506 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574507 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4508 # are too many (1000+) files with slight deviations from the
4509 # coding style. The most important part is that the include guard
4510 # is there, and that it's unique, not the name so this check is
4511 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144512 #
4513 # As code becomes more uniform, this could be made stricter.
4514
4515 guard_name_pattern_list = [
4516 # Anything with the right suffix (maybe with an extra _).
4517 r'\w+_H__?',
4518
Daniel Bratell39b5b062018-05-16 18:09:574519 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144520 r'\w+_h',
4521
4522 # Anything including the uppercase name of the file.
4523 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4524 upper_base_file_name)) + r'\w*',
4525 ]
4526 guard_name_pattern = '|'.join(guard_name_pattern_list)
4527 guard_pattern = input_api.re.compile(
4528 r'#ifndef\s+(' + guard_name_pattern + ')')
4529
4530 for line_number, line in enumerate(f.NewContents()):
4531 if 'no-include-guard-because-multiply-included' in line:
4532 guard_name = 'DUMMY' # To not trigger check outside the loop.
4533 break
4534
4535 if guard_name is None:
4536 match = guard_pattern.match(line)
4537 if match:
4538 guard_name = match.group(1)
4539 guard_line_number = line_number
4540
Daniel Bratell39b5b062018-05-16 18:09:574541 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454542 # don't match the chromium style guide, but new files should
4543 # get it right.
4544 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574545 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144546 errors.append(output_api.PresubmitPromptWarning(
4547 'Header using the wrong include guard name %s' % guard_name,
4548 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574549 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144550 else:
4551 # The line after #ifndef should have a #define of the same name.
4552 if line_number == guard_line_number + 1:
4553 expected_line = '#define %s' % guard_name
4554 if line != expected_line:
4555 errors.append(output_api.PresubmitPromptWarning(
4556 'Missing "%s" for include guard' % expected_line,
4557 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4558 'Expected: %r\nGot: %r' % (expected_line, line)))
4559
4560 if not seen_guard_end and line == '#endif // %s' % guard_name:
4561 seen_guard_end = True
4562 elif seen_guard_end:
4563 if line.strip() != '':
4564 errors.append(output_api.PresubmitPromptWarning(
4565 'Include guard %s not covering the whole file' % (
4566 guard_name), [f.LocalPath()]))
4567 break # Nothing else to check and enough to warn once.
4568
4569 if guard_name is None:
4570 errors.append(output_api.PresubmitPromptWarning(
4571 'Missing include guard %s' % expected_guard,
4572 [f.LocalPath()],
4573 'Missing include guard in %s\n'
4574 'Recommended name: %s\n'
4575 'This check can be disabled by having the string\n'
4576 'no-include-guard-because-multiply-included in the header.' %
4577 (f.LocalPath(), expected_guard)))
4578
4579 return errors
4580
4581
mostynbb639aca52015-01-07 20:31:234582def _CheckForWindowsLineEndings(input_api, output_api):
4583 """Check source code and known ascii text files for Windows style line
4584 endings.
4585 """
earthdok1b5e0ee2015-03-10 15:19:104586 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234587
4588 file_inclusion_pattern = (
4589 known_text_files,
4590 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4591 )
4592
mostynbb639aca52015-01-07 20:31:234593 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534594 source_file_filter = lambda f: input_api.FilterSourceFile(
4595 f, white_list=file_inclusion_pattern, black_list=None)
4596 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504597 include_file = False
4598 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234599 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504600 include_file = True
4601 if include_file:
4602 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234603
4604 if problems:
4605 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4606 'these files to contain Windows style line endings?\n' +
4607 '\n'.join(problems))]
4608
4609 return []
4610
4611
Vaclav Brozekd5de76a2018-03-17 07:57:504612def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134613 """Checks that all source files use SYSLOG properly."""
4614 syslog_files = []
4615 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564616 for line_number, line in f.ChangedContents():
4617 if 'SYSLOG' in line:
4618 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4619
pastarmovj89f7ee12016-09-20 14:58:134620 if syslog_files:
4621 return [output_api.PresubmitPromptWarning(
4622 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4623 ' calls.\nFiles to check:\n', items=syslog_files)]
4624 return []
4625
4626
[email protected]1f7b4172010-01-28 01:17:344627def CheckChangeOnUpload(input_api, output_api):
4628 results = []
4629 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474630 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284631 results.extend(
jam93a6ee792017-02-08 23:59:224632 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194633 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224634 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134635 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164636 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534637 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194638 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274639 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544640 return results
[email protected]ca8d1982009-02-19 16:33:124641
4642
[email protected]1bfb8322014-04-23 01:02:414643def GetTryServerMasterForBot(bot):
4644 """Returns the Try Server master for the given bot.
4645
[email protected]0bb112362014-07-26 04:38:324646 It tries to guess the master from the bot name, but may still fail
4647 and return None. There is no longer a default master.
4648 """
4649 # Potentially ambiguous bot names are listed explicitly.
4650 master_map = {
tandriie5587792016-07-14 00:34:504651 'chromium_presubmit': 'master.tryserver.chromium.linux',
4652 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414653 }
[email protected]0bb112362014-07-26 04:38:324654 master = master_map.get(bot)
4655 if not master:
wnwen4fbaab82016-05-25 12:54:364656 if 'android' in bot:
tandriie5587792016-07-14 00:34:504657 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364658 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504659 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324660 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504661 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324662 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504663 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324664 return master
[email protected]1bfb8322014-04-23 01:02:414665
4666
[email protected]ca8d1982009-02-19 16:33:124667def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544668 results = []
[email protected]1f7b4172010-01-28 01:17:344669 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574670 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544671 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274672 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344673 input_api,
4674 output_api,
[email protected]2fdd1f362013-01-16 03:56:034675 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274676
jam93a6ee792017-02-08 23:59:224677 results.extend(
4678 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544679 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4680 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384681 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4682 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414683 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4684 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544685 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144686
4687
4688def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144689 import os
4690 import sys
4691 from io import StringIO
4692
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144693 new_or_added_paths = set(f.LocalPath()
4694 for f in input_api.AffectedFiles()
4695 if (f.Action() == 'A' or f.Action() == 'M'))
4696 removed_paths = set(f.LocalPath()
4697 for f in input_api.AffectedFiles(include_deletes=True)
4698 if f.Action() == 'D')
4699
4700 affected_grds = [f for f in input_api.AffectedFiles()
4701 if (f.LocalPath().endswith('.grd') or
4702 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164703 if not affected_grds:
4704 return []
4705
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144706 affected_png_paths = [f.AbsoluteLocalPath()
4707 for f in input_api.AffectedFiles()
4708 if (f.LocalPath().endswith('.png'))]
4709
4710 # Check for screenshots. Developers can upload screenshots using
4711 # tools/translation/upload_screenshots.py which finds and uploads
4712 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4713 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4714 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4715 #
4716 # The logic here is as follows:
4717 #
4718 # - If the CL has a .png file under the screenshots directory for a grd
4719 # file, warn the developer. Actual images should never be checked into the
4720 # Chrome repo.
4721 #
4722 # - If the CL contains modified or new messages in grd files and doesn't
4723 # contain the corresponding .sha1 files, warn the developer to add images
4724 # and upload them via tools/translation/upload_screenshots.py.
4725 #
4726 # - If the CL contains modified or new messages in grd files and the
4727 # corresponding .sha1 files, everything looks good.
4728 #
4729 # - If the CL contains removed messages in grd files but the corresponding
4730 # .sha1 files aren't removed, warn the developer to remove them.
4731 unnecessary_screenshots = []
4732 missing_sha1 = []
4733 unnecessary_sha1_files = []
4734
4735
4736 def _CheckScreenshotAdded(screenshots_dir, message_id):
4737 sha1_path = input_api.os_path.join(
4738 screenshots_dir, message_id + '.png.sha1')
4739 if sha1_path not in new_or_added_paths:
4740 missing_sha1.append(sha1_path)
4741
4742
4743 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4744 sha1_path = input_api.os_path.join(
4745 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034746 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144747 unnecessary_sha1_files.append(sha1_path)
4748
meacer8c0d3832019-12-26 21:46:164749 try:
4750 old_sys_path = sys.path
4751 sys.path = sys.path + [input_api.os_path.join(
4752 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4753 from helper import grd_helper
4754 finally:
4755 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144756
4757 for f in affected_grds:
4758 file_path = f.LocalPath()
4759 old_id_to_msg_map = {}
4760 new_id_to_msg_map = {}
Mustafa Emre Acerd697ac92020-02-06 19:03:384761 # Note that this code doesn't check if the file has been deleted. This is
4762 # OK because it only uses the old and new file contents and doesn't load
4763 # the file via its path.
4764 # It's also possible that a file's content refers to a renamed or deleted
4765 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
4766 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
4767 # .grdp files.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144768 if file_path.endswith('.grdp'):
4769 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584770 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394771 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144772 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584773 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394774 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144775 else:
meacerff8a9b62019-12-10 19:43:584776 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144777 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584778 old_id_to_msg_map = grd_helper.GetGrdMessages(
4779 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144780 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584781 new_id_to_msg_map = grd_helper.GetGrdMessages(
4782 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144783
4784 # Compute added, removed and modified message IDs.
4785 old_ids = set(old_id_to_msg_map)
4786 new_ids = set(new_id_to_msg_map)
4787 added_ids = new_ids - old_ids
4788 removed_ids = old_ids - new_ids
4789 modified_ids = set([])
4790 for key in old_ids.intersection(new_ids):
4791 if (old_id_to_msg_map[key].FormatXml()
4792 != new_id_to_msg_map[key].FormatXml()):
4793 modified_ids.add(key)
4794
4795 grd_name, ext = input_api.os_path.splitext(
4796 input_api.os_path.basename(file_path))
4797 screenshots_dir = input_api.os_path.join(
4798 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4799
4800 # Check the screenshot directory for .png files. Warn if there is any.
4801 for png_path in affected_png_paths:
4802 if png_path.startswith(screenshots_dir):
4803 unnecessary_screenshots.append(png_path)
4804
4805 for added_id in added_ids:
4806 _CheckScreenshotAdded(screenshots_dir, added_id)
4807
4808 for modified_id in modified_ids:
4809 _CheckScreenshotAdded(screenshots_dir, modified_id)
4810
4811 for removed_id in removed_ids:
4812 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4813
4814 results = []
4815 if unnecessary_screenshots:
4816 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394817 'Do not include actual screenshots in the changelist. Run '
4818 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144819 sorted(unnecessary_screenshots)))
4820
4821 if missing_sha1:
4822 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394823 'You are adding or modifying UI strings.\n'
4824 'To ensure the best translations, take screenshots of the relevant UI '
4825 '(https://g.co/chrome/translation) and add these files to your '
4826 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144827
4828 if unnecessary_sha1_files:
4829 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394830 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144831 sorted(unnecessary_sha1_files)))
4832
4833 return results