blob: c939886f218d371e2128d73e9f538658b5ac5cf7 [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 (
Colin Blundell170d78c82020-03-12 13:56:0488 'java.net.URI;',
Michael Thiessen44457642020-02-06 00:24:1589 (
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/',
Alan Cutter04a00642020-03-02 01:45:20373 '^extensions/browser/',
374 '^extensions/renderer/',
danakj7a2b7082019-05-21 21:13:51375 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51376 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51377 '^ios/chrome/',
378 '^ios/components/',
379 '^ios/net/',
380 '^ios/web/',
381 '^ios/web_view/',
382 '^ipc/',
danakj7a2b7082019-05-21 21:13:51383 '^media/base/',
danakjc8576092019-11-26 19:01:36384 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51385 '^media/cast/',
386 '^media/cdm/',
387 '^media/device_monitors/',
danakj7a2b7082019-05-21 21:13:51388 '^media/filters/',
389 '^media/formats/',
390 '^media/gpu/',
391 '^media/mojo/',
danakj7a2b7082019-05-21 21:13:51392 '^media/renderers/',
danakj7a2b7082019-05-21 21:13:51393 '^net/',
394 '^ppapi/proxy/',
395 '^ppapi/shared_impl/',
396 '^ppapi/tests/',
397 '^ppapi/thunk/',
398 '^remoting/base/',
399 '^remoting/client/',
danakj7a2b7082019-05-21 21:13:51400 '^remoting/host/',
401 '^remoting/internal/',
danakj7a2b7082019-05-21 21:13:51402 '^remoting/protocol/',
danakj7a2b7082019-05-21 21:13:51403 '^services/',
danakj7a2b7082019-05-21 21:13:51404 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51405 '^tools/clang/base_bind_rewriters/', # Intentional.
406 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51407))
[email protected]127f18ec2012-06-16 05:05:59408
Daniel Bratell609102be2019-03-27 20:53:21409# Format: Sequence of tuples containing:
410# * String pattern or, if starting with a slash, a regular expression.
411# * Sequence of strings to show when the pattern matches.
412# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
413# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59414_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20415 (
Dave Tapuska98199b612019-07-10 13:30:44416 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53417 (
418 'New code should not use NULL. Use nullptr instead.',
419 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20420 False,
thomasandersone7caaa9b2017-03-29 19:22:53421 (),
422 ),
Peter Kasting94a56c42019-10-25 21:54:04423 (
424 r'/\busing namespace ',
425 (
426 'Using directives ("using namespace x") are banned by the Google Style',
427 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
428 'Explicitly qualify symbols or use using declarations ("using x::foo").',
429 ),
430 True,
431 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
432 ),
Antonio Gomes07300d02019-03-13 20:59:57433 # Make sure that gtest's FRIEND_TEST() macro is not used; the
434 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
435 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53436 (
[email protected]23e6cbc2012-06-16 18:51:20437 'FRIEND_TEST(',
438 (
[email protected]e3c945502012-06-26 20:01:49439 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20440 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
441 ),
442 False,
[email protected]7345da02012-11-27 14:31:49443 (),
[email protected]23e6cbc2012-06-16 18:51:20444 ),
445 (
Dave Tapuska98199b612019-07-10 13:30:44446 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53447 (
448 'Chrome clients wishing to select events on X windows should use',
449 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
450 'you are selecting events from the GPU process, or if you are using',
451 'an XDisplay other than gfx::GetXDisplay().',
452 ),
453 True,
454 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40455 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04456 r"^ui[\\/]gl[\\/].*\.cc$",
457 r"^media[\\/]gpu[\\/].*\.cc$",
458 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53459 ),
460 ),
461 (
Dave Tapuska98199b612019-07-10 13:30:44462 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20463 (
thomasanderson11aa41d2017-06-08 22:22:38464 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20465 ),
466 True,
467 (
Egor Paskoce145c42018-09-28 19:31:04468 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
469 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
470 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20471 ),
472 ),
473 (
tomhudsone2c14d552016-05-26 17:07:46474 'setMatrixClip',
475 (
476 'Overriding setMatrixClip() is prohibited; ',
477 'the base function is deprecated. ',
478 ),
479 True,
480 (),
481 ),
482 (
[email protected]52657f62013-05-20 05:30:31483 'SkRefPtr',
484 (
485 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22486 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31487 ),
488 True,
489 (),
490 ),
491 (
492 'SkAutoRef',
493 (
494 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22495 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31496 ),
497 True,
498 (),
499 ),
500 (
501 'SkAutoTUnref',
502 (
503 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22504 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31505 ),
506 True,
507 (),
508 ),
509 (
510 'SkAutoUnref',
511 (
512 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
513 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22514 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31515 ),
516 True,
517 (),
518 ),
[email protected]d89eec82013-12-03 14:10:59519 (
520 r'/HANDLE_EINTR\(.*close',
521 (
522 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
523 'descriptor will be closed, and it is incorrect to retry the close.',
524 'Either call close directly and ignore its return value, or wrap close',
525 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
526 ),
527 True,
528 (),
529 ),
530 (
531 r'/IGNORE_EINTR\((?!.*close)',
532 (
533 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
534 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
535 ),
536 True,
537 (
538 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04539 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
540 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59541 ),
542 ),
[email protected]ec5b3f02014-04-04 18:43:43543 (
544 r'/v8::Extension\(',
545 (
546 'Do not introduce new v8::Extensions into the code base, use',
547 'gin::Wrappable instead. See http://crbug.com/334679',
548 ),
549 True,
[email protected]f55c90ee62014-04-12 00:50:03550 (
Egor Paskoce145c42018-09-28 19:31:04551 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03552 ),
[email protected]ec5b3f02014-04-04 18:43:43553 ),
skyostilf9469f72015-04-20 10:38:52554 (
jame2d1a952016-04-02 00:27:10555 '#pragma comment(lib,',
556 (
557 'Specify libraries to link with in build files and not in the source.',
558 ),
559 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41560 (
tzik3f295992018-12-04 20:32:23561 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04562 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41563 ),
jame2d1a952016-04-02 00:27:10564 ),
fdorayc4ac18d2017-05-01 21:39:59565 (
Gabriel Charette7cc6c432018-04-25 20:52:02566 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59567 (
568 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
569 ),
570 False,
571 (),
572 ),
573 (
Gabriel Charette7cc6c432018-04-25 20:52:02574 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59575 (
576 'Consider using THREAD_CHECKER macros instead of the class directly.',
577 ),
578 False,
579 (),
580 ),
dbeamb6f4fde2017-06-15 04:03:06581 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06582 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
583 (
584 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
585 'deprecated (http://crbug.com/634507). Please avoid converting away',
586 'from the Time types in Chromium code, especially if any math is',
587 'being done on time values. For interfacing with platform/library',
588 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
589 'type converter methods instead. For faking TimeXXX values (for unit',
590 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
591 'other use cases, please contact base/time/OWNERS.',
592 ),
593 False,
594 (),
595 ),
596 (
dbeamb6f4fde2017-06-15 04:03:06597 'CallJavascriptFunctionUnsafe',
598 (
599 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
600 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
601 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
602 ),
603 False,
604 (
Egor Paskoce145c42018-09-28 19:31:04605 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
606 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
607 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06608 ),
609 ),
dskiba1474c2bfd62017-07-20 02:19:24610 (
611 'leveldb::DB::Open',
612 (
613 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
614 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
615 "Chrome's tracing, making their memory usage visible.",
616 ),
617 True,
618 (
619 r'^third_party/leveldatabase/.*\.(cc|h)$',
620 ),
Gabriel Charette0592c3a2017-07-26 12:02:04621 ),
622 (
Chris Mumfordc38afb62017-10-09 17:55:08623 'leveldb::NewMemEnv',
624 (
625 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58626 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
627 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08628 ),
629 True,
630 (
631 r'^third_party/leveldatabase/.*\.(cc|h)$',
632 ),
633 ),
634 (
Gabriel Charetted9839bc2017-07-29 14:17:47635 'RunLoop::QuitCurrent',
636 (
Robert Liao64b7ab22017-08-04 23:03:43637 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
638 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47639 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41640 False,
Gabriel Charetted9839bc2017-07-29 14:17:47641 (),
Gabriel Charettea44975052017-08-21 23:14:04642 ),
643 (
644 'base::ScopedMockTimeMessageLoopTaskRunner',
645 (
Gabriel Charette87cc1af2018-04-25 20:52:51646 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11647 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51648 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
649 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
650 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04651 ),
Gabriel Charette87cc1af2018-04-25 20:52:51652 False,
Gabriel Charettea44975052017-08-21 23:14:04653 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57654 ),
655 (
Dave Tapuska98199b612019-07-10 13:30:44656 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57657 (
658 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02659 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57660 ),
661 True,
662 (),
Francois Doray43670e32017-09-27 12:40:38663 ),
664 (
Peter Kasting991618a62019-06-17 22:00:09665 r'/\bstd::stoi\b',
666 (
667 'std::stoi uses exceptions to communicate results. ',
668 'Use base::StringToInt() instead.',
669 ),
670 True,
671 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
672 ),
673 (
674 r'/\bstd::stol\b',
675 (
676 'std::stol uses exceptions to communicate results. ',
677 'Use base::StringToInt() instead.',
678 ),
679 True,
680 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
681 ),
682 (
683 r'/\bstd::stoul\b',
684 (
685 'std::stoul uses exceptions to communicate results. ',
686 'Use base::StringToUint() instead.',
687 ),
688 True,
689 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
690 ),
691 (
692 r'/\bstd::stoll\b',
693 (
694 'std::stoll uses exceptions to communicate results. ',
695 'Use base::StringToInt64() instead.',
696 ),
697 True,
698 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
699 ),
700 (
701 r'/\bstd::stoull\b',
702 (
703 'std::stoull uses exceptions to communicate results. ',
704 'Use base::StringToUint64() instead.',
705 ),
706 True,
707 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
708 ),
709 (
710 r'/\bstd::stof\b',
711 (
712 'std::stof uses exceptions to communicate results. ',
713 'For locale-independent values, e.g. reading numbers from disk',
714 'profiles, use base::StringToDouble().',
715 'For user-visible values, parse using ICU.',
716 ),
717 True,
718 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
719 ),
720 (
721 r'/\bstd::stod\b',
722 (
723 'std::stod uses exceptions to communicate results. ',
724 'For locale-independent values, e.g. reading numbers from disk',
725 'profiles, use base::StringToDouble().',
726 'For user-visible values, parse using ICU.',
727 ),
728 True,
729 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
730 ),
731 (
732 r'/\bstd::stold\b',
733 (
734 'std::stold uses exceptions to communicate results. ',
735 'For locale-independent values, e.g. reading numbers from disk',
736 'profiles, use base::StringToDouble().',
737 'For user-visible values, parse using ICU.',
738 ),
739 True,
740 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
741 ),
742 (
Daniel Bratell69334cc2019-03-26 11:07:45743 r'/\bstd::to_string\b',
744 (
745 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09746 'For locale-independent strings, e.g. writing numbers to disk',
747 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45748 'For user-visible strings, use base::FormatNumber() and',
749 'the related functions in base/i18n/number_formatting.h.',
750 ),
Peter Kasting991618a62019-06-17 22:00:09751 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21752 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45753 ),
754 (
755 r'/\bstd::shared_ptr\b',
756 (
757 'std::shared_ptr should not be used. Use scoped_refptr instead.',
758 ),
759 True,
Andreas Haas63f58792019-11-07 10:56:44760 [_THIRD_PARTY_EXCEPT_BLINK,
761 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
762 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21763 ),
764 (
Peter Kasting991618a62019-06-17 22:00:09765 r'/\bstd::weak_ptr\b',
766 (
767 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
768 ),
769 True,
770 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
771 ),
772 (
Daniel Bratell609102be2019-03-27 20:53:21773 r'/\blong long\b',
774 (
775 'long long is banned. Use stdint.h if you need a 64 bit number.',
776 ),
777 False, # Only a warning since it is already used.
778 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
779 ),
780 (
781 r'/\bstd::bind\b',
782 (
783 'std::bind is banned because of lifetime risks.',
784 'Use base::BindOnce or base::BindRepeating instead.',
785 ),
786 True,
787 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
788 ),
789 (
790 r'/\b#include <chrono>\b',
791 (
792 '<chrono> overlaps with Time APIs in base. Keep using',
793 'base classes.',
794 ),
795 True,
796 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
797 ),
798 (
799 r'/\b#include <exception>\b',
800 (
801 'Exceptions are banned and disabled in Chromium.',
802 ),
803 True,
804 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
805 ),
806 (
807 r'/\bstd::function\b',
808 (
809 'std::function is banned. Instead use base::Callback which directly',
810 'supports Chromium\'s weak pointers, ref counting and more.',
811 ),
Peter Kasting991618a62019-06-17 22:00:09812 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21813 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
814 ),
815 (
816 r'/\b#include <random>\b',
817 (
818 'Do not use any random number engines from <random>. Instead',
819 'use base::RandomBitGenerator.',
820 ),
821 True,
822 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
823 ),
824 (
825 r'/\bstd::ratio\b',
826 (
827 'std::ratio is banned by the Google Style Guide.',
828 ),
829 True,
830 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45831 ),
832 (
Francois Doray43670e32017-09-27 12:40:38833 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
834 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
835 (
836 'Use the new API in base/threading/thread_restrictions.h.',
837 ),
Gabriel Charette04b138f2018-08-06 00:03:22838 False,
Francois Doray43670e32017-09-27 12:40:38839 (),
840 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38841 (
danakj7a2b7082019-05-21 21:13:51842 r'/\bbase::Bind\(',
843 (
844 'Please use base::Bind{Once,Repeating} instead',
845 'of base::Bind. (crbug.com/714018)',
846 ),
847 False,
Erik Staaba737d7602019-11-25 18:41:07848 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51849 ),
850 (
851 r'/\bbase::Callback[<:]',
852 (
853 'Please use base::{Once,Repeating}Callback instead',
854 'of base::Callback. (crbug.com/714018)',
855 ),
856 False,
Erik Staaba737d7602019-11-25 18:41:07857 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51858 ),
859 (
860 r'/\bbase::Closure\b',
861 (
862 'Please use base::{Once,Repeating}Closure instead',
863 'of base::Closure. (crbug.com/714018)',
864 ),
865 False,
Erik Staaba737d7602019-11-25 18:41:07866 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51867 ),
868 (
Michael Giuffrida7f93d6922019-04-19 14:39:58869 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19870 (
871 'RunMessageLoop is deprecated, use RunLoop instead.',
872 ),
873 False,
874 (),
875 ),
876 (
Dave Tapuska98199b612019-07-10 13:30:44877 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19878 (
879 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
880 ),
881 False,
882 (),
883 ),
884 (
Dave Tapuska98199b612019-07-10 13:30:44885 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19886 (
887 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
888 "if you're convinced you need this.",
889 ),
890 False,
891 (),
892 ),
893 (
Dave Tapuska98199b612019-07-10 13:30:44894 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19895 (
896 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04897 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19898 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
899 'async events instead of flushing threads.',
900 ),
901 False,
902 (),
903 ),
904 (
905 r'MessageLoopRunner',
906 (
907 'MessageLoopRunner is deprecated, use RunLoop instead.',
908 ),
909 False,
910 (),
911 ),
912 (
Dave Tapuska98199b612019-07-10 13:30:44913 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19914 (
915 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
916 "gab@ if you found a use case where this is the only solution.",
917 ),
918 False,
919 (),
920 ),
921 (
Victor Costane48a2e82019-03-15 22:02:34922 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16923 (
Victor Costane48a2e82019-03-15 22:02:34924 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16925 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
926 ),
927 True,
928 (
929 r'^sql/initialization\.(cc|h)$',
930 r'^third_party/sqlite/.*\.(c|cc|h)$',
931 ),
932 ),
Matt Menke7f520a82018-03-28 21:38:37933 (
934 'net::URLFetcher',
935 (
936 'net::URLFetcher should no longer be used in content embedders. ',
937 'Instead, use network::SimpleURLLoader instead, which supports ',
938 'an out-of-process network stack. ',
939 'net::URLFetcher may still be used in binaries that do not embed',
940 'content.',
941 ),
Matt Menke59716d02018-04-05 12:45:53942 False,
Matt Menke7f520a82018-03-28 21:38:37943 (
Egor Paskoce145c42018-09-28 19:31:04944 r'^ios[\\/].*\.(cc|h)$',
945 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37946 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04947 r'^net[\\/].*\.(cc|h)$',
948 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43949 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37950 ),
951 ),
jdoerried7d10ab2018-04-27 10:46:13952 (
Dave Tapuska98199b612019-07-10 13:30:44953 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47954 (
955 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
956 'base::RandomShuffle instead.'
957 ),
958 True,
959 (),
960 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24961 (
962 'ios/web/public/test/http_server',
963 (
964 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
965 ),
966 False,
967 (),
968 ),
Robert Liao764c9492019-01-24 18:46:28969 (
970 'GetAddressOf',
971 (
972 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46973 'implicated in a few leaks. Use operator& instead. See ',
974 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28975 ),
976 True,
977 (),
978 ),
Antonio Gomes07300d02019-03-13 20:59:57979 (
980 'DEFINE_TYPE_CASTS',
981 (
982 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
983 '//third_party/blink/renderer/platform/casting.h.'
984 ),
985 True,
986 (
987 r'^third_party/blink/renderer/.*\.(cc|h)$',
988 ),
989 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38990 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45991 r'/\bIsHTML.+Element\(\b',
992 (
993 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
994 ' helpers IsA<HTMLXXXXElement> from ',
995 '//third_party/blink/renderer/platform/casting.h.'
996 ),
997 False,
998 (
999 r'^third_party/blink/renderer/.*\.(cc|h)$',
1000 ),
1001 ),
1002 (
1003 r'/\bToHTML.+Element(|OrNull)\(\b',
1004 (
1005 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1006 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1007 'and DynamicTo<HTMLXXXXElement> from ',
1008 '//third_party/blink/renderer/platform/casting.h.'
1009 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1010 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1011 ),
1012 False,
1013 (
1014 r'^third_party/blink/renderer/.*\.(cc|h)$',
1015 ),
1016 ),
1017 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371018 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381019 (
1020 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1021 ),
1022 True,
1023 (),
1024 ),
Ben Lewisa9514602019-04-29 17:53:051025 (
1026 'SHFileOperation',
1027 (
1028 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1029 'complex functions to achieve the same goals. Use IFileOperation for ',
1030 'any esoteric actions instead.'
1031 ),
1032 True,
1033 (),
1034 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181035 (
Cliff Smolinsky81951642019-04-30 21:39:511036 'StringFromGUID2',
1037 (
1038 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1039 'Use base::win::String16FromGUID instead.'
1040 ),
1041 True,
1042 (
1043 r'/base/win/win_util_unittest.cc'
1044 ),
1045 ),
1046 (
1047 'StringFromCLSID',
1048 (
1049 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1050 'Use base::win::String16FromGUID instead.'
1051 ),
1052 True,
1053 (
1054 r'/base/win/win_util_unittest.cc'
1055 ),
1056 ),
1057 (
Avi Drissman7382afa02019-04-29 23:27:131058 'kCFAllocatorNull',
1059 (
1060 'The use of kCFAllocatorNull with the NoCopy creation of ',
1061 'CoreFoundation types is prohibited.',
1062 ),
1063 True,
1064 (),
1065 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291066 (
1067 'mojo::ConvertTo',
1068 (
1069 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1070 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1071 'StringTraits if you would like to convert between custom types and',
1072 'the wire format of mojom types.'
1073 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221074 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291075 (
Wezf89dec092019-09-11 19:38:331076 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1077 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291078 r'^third_party/blink/.*\.(cc|h)$',
1079 r'^content/renderer/.*\.(cc|h)$',
1080 ),
1081 ),
Robert Liao1d78df52019-11-11 20:02:011082 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161083 'GetInterfaceProvider',
1084 (
1085 'InterfaceProvider is deprecated.',
1086 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1087 'or Platform::GetBrowserInterfaceBroker.'
1088 ),
1089 False,
1090 (),
1091 ),
1092 (
Robert Liao1d78df52019-11-11 20:02:011093 'CComPtr',
1094 (
1095 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1096 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1097 'details.'
1098 ),
1099 False,
1100 (),
1101 ),
Xiaohan Wang72bd2ba2020-02-18 21:38:201102 (
1103 r'/\b(IFACE|STD)METHOD_?\(',
1104 (
1105 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1106 'Instead, always use IFACEMETHODIMP in the declaration.'
1107 ),
1108 False,
1109 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1110 ),
Allen Bauer53b43fb12020-03-12 17:21:471111 (
1112 'set_owned_by_client',
1113 (
1114 'set_owned_by_client is deprecated.',
1115 'views::View already owns the child views by default. This introduces ',
1116 'a competing ownership model which makes the code difficult to reason ',
1117 'about. See http://crbug.com/1044687 for more details.'
1118 ),
1119 False,
1120 (),
1121 ),
[email protected]127f18ec2012-06-16 05:05:591122)
1123
Mario Sanchez Prada2472cab2019-09-18 10:58:311124# Format: Sequence of tuples containing:
1125# * String pattern or, if starting with a slash, a regular expression.
1126# * Sequence of strings to show when the pattern matches.
1127_DEPRECATED_MOJO_TYPES = (
1128 (
1129 r'/\bmojo::AssociatedBinding\b',
1130 (
1131 'mojo::AssociatedBinding<Interface> is deprecated.',
1132 'Use mojo::AssociatedReceiver<Interface> instead.',
1133 ),
1134 ),
1135 (
1136 r'/\bmojo::AssociatedBindingSet\b',
1137 (
1138 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1139 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1140 ),
1141 ),
1142 (
1143 r'/\bmojo::AssociatedInterfacePtr\b',
1144 (
1145 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1146 'Use mojo::AssociatedRemote<Interface> instead.',
1147 ),
1148 ),
1149 (
1150 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1151 (
1152 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1153 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1154 ),
1155 ),
1156 (
1157 r'/\bmojo::AssociatedInterfaceRequest\b',
1158 (
1159 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1160 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1161 ),
1162 ),
1163 (
1164 r'/\bmojo::Binding\b',
1165 (
1166 'mojo::Binding<Interface> is deprecated.',
1167 'Use mojo::Receiver<Interface> instead.',
1168 ),
1169 ),
1170 (
1171 r'/\bmojo::BindingSet\b',
1172 (
1173 'mojo::BindingSet<Interface> is deprecated.',
1174 'Use mojo::ReceiverSet<Interface> instead.',
1175 ),
1176 ),
1177 (
1178 r'/\bmojo::InterfacePtr\b',
1179 (
1180 'mojo::InterfacePtr<Interface> is deprecated.',
1181 'Use mojo::Remote<Interface> instead.',
1182 ),
1183 ),
1184 (
1185 r'/\bmojo::InterfacePtrInfo\b',
1186 (
1187 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1188 'Use mojo::PendingRemote<Interface> instead.',
1189 ),
1190 ),
1191 (
1192 r'/\bmojo::InterfaceRequest\b',
1193 (
1194 'mojo::InterfaceRequest<Interface> is deprecated.',
1195 'Use mojo::PendingReceiver<Interface> instead.',
1196 ),
1197 ),
1198 (
1199 r'/\bmojo::MakeRequest\b',
1200 (
1201 'mojo::MakeRequest is deprecated.',
1202 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1203 ),
1204 ),
1205 (
1206 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1207 (
1208 'mojo::MakeRequest is deprecated.',
1209 'Use mojo::AssociatedRemote::'
1210 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1211 ),
1212 ),
1213 (
1214 r'/\bmojo::MakeStrongBinding\b',
1215 (
1216 'mojo::MakeStrongBinding is deprecated.',
1217 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1218 'mojo::MakeSelfOwnedReceiver() instead.',
1219 ),
1220 ),
1221 (
1222 r'/\bmojo::MakeStrongAssociatedBinding\b',
1223 (
1224 'mojo::MakeStrongAssociatedBinding is deprecated.',
1225 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1226 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1227 ),
1228 ),
1229 (
1230 r'/\bmojo::StrongAssociatedBindingSet\b',
1231 (
1232 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1233 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1234 ),
1235 ),
1236 (
1237 r'/\bmojo::StrongBindingSet\b',
1238 (
1239 'mojo::StrongBindingSet<Interface> is deprecated.',
1240 'Use mojo::UniqueReceiverSet<Interface> instead.',
1241 ),
1242 ),
1243)
wnwenbdc444e2016-05-25 13:44:151244
mlamouria82272622014-09-16 18:45:041245_IPC_ENUM_TRAITS_DEPRECATED = (
1246 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501247 'See http://www.chromium.org/Home/chromium-security/education/'
1248 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041249
Stephen Martinis97a394142018-06-07 23:06:051250_LONG_PATH_ERROR = (
1251 'Some files included in this CL have file names that are too long (> 200'
1252 ' characters). If committed, these files will cause issues on Windows. See'
1253 ' https://crbug.com/612667 for more details.'
1254)
1255
Shenghua Zhangbfaa38b82017-11-16 21:58:021256_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041257 r".*[\\/]BuildHooksAndroidImpl\.java",
1258 r".*[\\/]LicenseContentProvider\.java",
1259 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281260 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021261]
[email protected]127f18ec2012-06-16 05:05:591262
Mohamed Heikald048240a2019-11-12 16:57:371263# List of image extensions that are used as resources in chromium.
1264_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1265
Sean Kau46e29bc2017-08-28 16:31:161266# These paths contain test data and other known invalid JSON files.
1267_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041268 r'test[\\/]data[\\/]',
1269 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1270 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041271 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431272 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161273]
1274
1275
[email protected]b00342e7f2013-03-26 16:21:541276_VALID_OS_MACROS = (
1277 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081278 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121280 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541281 'OS_BSD',
1282 'OS_CAT', # For testing.
1283 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041284 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541285 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371286 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541287 'OS_IOS',
1288 'OS_LINUX',
1289 'OS_MACOSX',
1290 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211291 'OS_NACL_NONSFI',
1292 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121293 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541294 'OS_OPENBSD',
1295 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371296 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541297 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541298 'OS_WIN',
1299)
1300
1301
agrievef32bcc72016-04-04 14:57:401302_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391303 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'base/android/jni_generator/jni_generator.pydeps',
1305 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221306 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361307 'build/android/gyp/aar.pydeps',
1308 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271309 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361310 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381311 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361312 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111313 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361314 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361315 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361316 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111317 'build/android/gyp/create_app_bundle_apks.pydeps',
1318 'build/android/gyp/create_app_bundle.pydeps',
1319 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361320 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221321 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361322 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591323 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361324 'build/android/gyp/dex.pydeps',
1325 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361326 'build/android/gyp/filter_zip.pydeps',
1327 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361328 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361329 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581330 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361331 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261332 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve5853fbd2020-02-20 17:26:011333 'build/android/gyp/jetify_jar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361334 'build/android/gyp/jinja_template.pydeps',
1335 'build/android/gyp/lint.pydeps',
1336 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361337 'build/android/gyp/merge_manifest.pydeps',
1338 'build/android/gyp/prepare_resources.pydeps',
1339 'build/android/gyp/proguard.pydeps',
Peter Wen578730b2020-03-19 19:55:461340 'build/android/gyp/turbine.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241341 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361342 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461343 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561344 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361345 'build/android/incremental_install/generate_android_manifest.pydeps',
1346 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221347 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401348 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041349 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361350 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411351 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051352 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191353 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431354 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021355 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401356]
1357
wnwenbdc444e2016-05-25 13:44:151358
agrievef32bcc72016-04-04 14:57:401359_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421360 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131361 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421362 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1363 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131364 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191365 ('third_party/blink/renderer/bindings/scripts/'
1366 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061367 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221368 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401369]
1370
wnwenbdc444e2016-05-25 13:44:151371
agrievef32bcc72016-04-04 14:57:401372_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1373
1374
Eric Boren6fd2b932018-01-25 15:05:081375# Bypass the AUTHORS check for these accounts.
1376_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591377 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451378 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591379 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521380 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1381 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041382 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271383 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041384 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301385 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081386
1387
Daniel Bratell65b033262019-04-23 08:17:061388def _IsCPlusPlusFile(input_api, file_path):
1389 """Returns True if this file contains C++-like code (and not Python,
1390 Go, Java, MarkDown, ...)"""
1391
1392 ext = input_api.os_path.splitext(file_path)[1]
1393 # This list is compatible with CppChecker.IsCppFile but we should
1394 # consider adding ".c" to it. If we do that we can use this function
1395 # at more places in the code.
1396 return ext in (
1397 '.h',
1398 '.cc',
1399 '.cpp',
1400 '.m',
1401 '.mm',
1402 )
1403
1404def _IsCPlusPlusHeaderFile(input_api, file_path):
1405 return input_api.os_path.splitext(file_path)[1] == ".h"
1406
1407
1408def _IsJavaFile(input_api, file_path):
1409 return input_api.os_path.splitext(file_path)[1] == ".java"
1410
1411
1412def _IsProtoFile(input_api, file_path):
1413 return input_api.os_path.splitext(file_path)[1] == ".proto"
1414
[email protected]55459852011-08-10 15:17:191415def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1416 """Attempts to prevent use of functions intended only for testing in
1417 non-testing code. For now this is just a best-effort implementation
1418 that ignores header files and may have some false positives. A
1419 better implementation would probably need a proper C++ parser.
1420 """
1421 # We only scan .cc files and the like, as the declaration of
1422 # for-testing functions in header files are hard to distinguish from
1423 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491424 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191425
jochenc0d4808c2015-07-27 09:25:421426 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191427 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091428 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191429 exclusion_pattern = input_api.re.compile(
1430 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1431 base_function_pattern, base_function_pattern))
1432
1433 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441434 black_list = (_EXCLUDED_PATHS +
1435 _TEST_CODE_EXCLUDED_PATHS +
1436 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191437 return input_api.FilterSourceFile(
1438 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491439 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191440 black_list=black_list)
1441
1442 problems = []
1443 for f in input_api.AffectedSourceFiles(FilterFile):
1444 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241445 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031446 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461447 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031448 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191449 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031450 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191451
1452 if problems:
[email protected]f7051d52013-04-02 18:31:421453 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031454 else:
1455 return []
[email protected]55459852011-08-10 15:17:191456
1457
Vaclav Brozek7dbc28c2018-03-27 08:35:231458def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1459 """This is a simplified version of
1460 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1461 """
1462 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1463 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1464 name_pattern = r'ForTest(s|ing)?'
1465 # Describes an occurrence of "ForTest*" inside a // comment.
1466 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1467 # Catch calls.
1468 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1469 # Ignore definitions. (Comments are ignored separately.)
1470 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1471
1472 problems = []
1473 sources = lambda x: input_api.FilterSourceFile(
1474 x,
1475 black_list=(('(?i).*test', r'.*\/junit\/')
1476 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491477 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231478 )
1479 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1480 local_path = f.LocalPath()
1481 is_inside_javadoc = False
1482 for line_number, line in f.ChangedContents():
1483 if is_inside_javadoc and javadoc_end_re.search(line):
1484 is_inside_javadoc = False
1485 if not is_inside_javadoc and javadoc_start_re.search(line):
1486 is_inside_javadoc = True
1487 if is_inside_javadoc:
1488 continue
1489 if (inclusion_re.search(line) and
1490 not comment_re.search(line) and
1491 not exclusion_re.search(line)):
1492 problems.append(
1493 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1494
1495 if problems:
1496 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1497 else:
1498 return []
1499
1500
[email protected]10689ca2011-09-02 02:31:541501def _CheckNoIOStreamInHeaders(input_api, output_api):
1502 """Checks to make sure no .h files include <iostream>."""
1503 files = []
1504 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1505 input_api.re.MULTILINE)
1506 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1507 if not f.LocalPath().endswith('.h'):
1508 continue
1509 contents = input_api.ReadFile(f)
1510 if pattern.search(contents):
1511 files.append(f)
1512
1513 if len(files):
yolandyandaabc6d2016-04-18 18:29:391514 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061515 'Do not #include <iostream> in header files, since it inserts static '
1516 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541517 '#include <ostream>. See http://crbug.com/94794',
1518 files) ]
1519 return []
1520
Danil Chapovalov3518f362018-08-11 16:13:431521def _CheckNoStrCatRedefines(input_api, output_api):
1522 """Checks no windows headers with StrCat redefined are included directly."""
1523 files = []
1524 pattern_deny = input_api.re.compile(
1525 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1526 input_api.re.MULTILINE)
1527 pattern_allow = input_api.re.compile(
1528 r'^#include\s"base/win/windows_defines.inc"',
1529 input_api.re.MULTILINE)
1530 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1531 contents = input_api.ReadFile(f)
1532 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1533 files.append(f.LocalPath())
1534
1535 if len(files):
1536 return [output_api.PresubmitError(
1537 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1538 'directly since they pollute code with StrCat macro. Instead, '
1539 'include matching header from base/win. See http://crbug.com/856536',
1540 files) ]
1541 return []
1542
[email protected]10689ca2011-09-02 02:31:541543
[email protected]72df4e782012-06-21 16:28:181544def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521545 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181546 problems = []
1547 for f in input_api.AffectedFiles():
1548 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1549 continue
1550
1551 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041552 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181553 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1554
1555 if not problems:
1556 return []
1557 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1558 '\n'.join(problems))]
1559
Dominic Battre033531052018-09-24 15:45:341560def _CheckNoDISABLETypoInTests(input_api, output_api):
1561 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1562
1563 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1564 instead of DISABLED_. To filter false positives, reports are only generated
1565 if a corresponding MAYBE_ line exists.
1566 """
1567 problems = []
1568
1569 # The following two patterns are looked for in tandem - is a test labeled
1570 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1571 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1572 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1573
1574 # This is for the case that a test is disabled on all platforms.
1575 full_disable_pattern = input_api.re.compile(
1576 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1577 input_api.re.MULTILINE)
1578
Katie Df13948e2018-09-25 07:33:441579 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341580 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1581 continue
1582
1583 # Search for MABYE_, DISABLE_ pairs.
1584 disable_lines = {} # Maps of test name to line number.
1585 maybe_lines = {}
1586 for line_num, line in f.ChangedContents():
1587 disable_match = disable_pattern.search(line)
1588 if disable_match:
1589 disable_lines[disable_match.group(1)] = line_num
1590 maybe_match = maybe_pattern.search(line)
1591 if maybe_match:
1592 maybe_lines[maybe_match.group(1)] = line_num
1593
1594 # Search for DISABLE_ occurrences within a TEST() macro.
1595 disable_tests = set(disable_lines.keys())
1596 maybe_tests = set(maybe_lines.keys())
1597 for test in disable_tests.intersection(maybe_tests):
1598 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1599
1600 contents = input_api.ReadFile(f)
1601 full_disable_match = full_disable_pattern.search(contents)
1602 if full_disable_match:
1603 problems.append(' %s' % f.LocalPath())
1604
1605 if not problems:
1606 return []
1607 return [
1608 output_api.PresubmitPromptWarning(
1609 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1610 '\n'.join(problems))
1611 ]
1612
[email protected]72df4e782012-06-21 16:28:181613
danakj61c1aa22015-10-26 19:55:521614def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571615 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521616 errors = []
1617 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1618 input_api.re.MULTILINE)
1619 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1620 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1621 continue
1622 for lnum, line in f.ChangedContents():
1623 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171624 errors.append(output_api.PresubmitError(
1625 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571626 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171627 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521628 return errors
1629
1630
Makoto Shimazu3ad422cd2019-05-08 02:35:141631def _FindHistogramNameInChunk(histogram_name, chunk):
1632 """Tries to find a histogram name or prefix in a line.
1633
1634 Returns the existence of the histogram name, or None if it needs more chunk
1635 to determine."""
mcasasb7440c282015-02-04 14:52:191636 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1637 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141638 if '<affected-histogram' in chunk:
1639 # If the tag is not completed, needs more chunk to get the name.
1640 if not '>' in chunk:
1641 return None
1642 if not 'name="' in chunk:
1643 return False
1644 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1645 # expect the only attribute is the name.
1646 histogram_prefix = chunk.split('"')[1]
1647 return histogram_prefix in histogram_name
1648 # Typically the whole histogram name should in the line.
1649 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191650
1651
1652def _CheckUmaHistogramChanges(input_api, output_api):
1653 """Check that UMA histogram names in touched lines can still be found in other
1654 lines of the patch or in histograms.xml. Note that this check would not catch
1655 the reverse: changes in histograms.xml not matched in the code itself."""
1656 touched_histograms = []
1657 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471658 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1659 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1660 name_pattern = r'"(.*?)"'
1661 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1662 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1663 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1664 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1665 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171666 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191667 for f in input_api.AffectedFiles():
1668 # If histograms.xml itself is modified, keep the modified lines for later.
1669 if f.LocalPath().endswith(('histograms.xml')):
1670 histograms_xml_modifications = f.ChangedContents()
1671 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471672 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1673 single_line_re = single_line_c_re
1674 split_line_prefix_re = split_line_c_prefix_re
1675 elif f.LocalPath().endswith(('java')):
1676 single_line_re = single_line_java_re
1677 split_line_prefix_re = split_line_java_prefix_re
1678 else:
mcasasb7440c282015-02-04 14:52:191679 continue
1680 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171681 if last_line_matched_prefix:
1682 suffix_found = split_line_suffix_re.search(line)
1683 if suffix_found :
1684 touched_histograms.append([suffix_found.group(1), f, line_num])
1685 last_line_matched_prefix = False
1686 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061687 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191688 if found:
1689 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171690 continue
1691 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191692
1693 # Search for the touched histogram names in the local modifications to
1694 # histograms.xml, and, if not found, on the base histograms.xml file.
1695 unmatched_histograms = []
1696 for histogram_info in touched_histograms:
1697 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141698 chunk = ''
mcasasb7440c282015-02-04 14:52:191699 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141700 chunk += line
1701 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1702 if histogram_name_found is None:
1703 continue
1704 chunk = ''
mcasasb7440c282015-02-04 14:52:191705 if histogram_name_found:
1706 break
1707 if not histogram_name_found:
1708 unmatched_histograms.append(histogram_info)
1709
eromanb90c82e7e32015-04-01 15:13:491710 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191711 problems = []
1712 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491713 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191714 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451715 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191716 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141717 chunk = ''
mcasasb7440c282015-02-04 14:52:191718 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141719 chunk += line
1720 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1721 chunk)
1722 if histogram_name_found is None:
1723 continue
1724 chunk = ''
mcasasb7440c282015-02-04 14:52:191725 if histogram_name_found:
1726 break
1727 if not histogram_name_found:
1728 problems.append(' [%s:%d] %s' %
1729 (f.LocalPath(), line_num, histogram_name))
1730
1731 if not problems:
1732 return []
1733 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1734 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491735 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191736
wnwenbdc444e2016-05-25 13:44:151737
yolandyandaabc6d2016-04-18 18:29:391738def _CheckFlakyTestUsage(input_api, output_api):
1739 """Check that FlakyTest annotation is our own instead of the android one"""
1740 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1741 files = []
1742 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1743 if f.LocalPath().endswith('Test.java'):
1744 if pattern.search(input_api.ReadFile(f)):
1745 files.append(f)
1746 if len(files):
1747 return [output_api.PresubmitError(
1748 'Use org.chromium.base.test.util.FlakyTest instead of '
1749 'android.test.FlakyTest',
1750 files)]
1751 return []
mcasasb7440c282015-02-04 14:52:191752
wnwenbdc444e2016-05-25 13:44:151753
[email protected]8ea5d4b2011-09-13 21:49:221754def _CheckNoNewWStrings(input_api, output_api):
1755 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271756 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221757 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201758 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571759 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341760 '/win/' in f.LocalPath() or
1761 'chrome_elf' in f.LocalPath() or
1762 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201763 continue
[email protected]8ea5d4b2011-09-13 21:49:221764
[email protected]a11dbe9b2012-08-07 01:32:581765 allowWString = False
[email protected]b5c24292011-11-28 14:38:201766 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581767 if 'presubmit: allow wstring' in line:
1768 allowWString = True
1769 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271770 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581771 allowWString = False
1772 else:
1773 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221774
[email protected]55463aa62011-10-12 00:48:271775 if not problems:
1776 return []
1777 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581778 ' If you are calling a cross-platform API that accepts a wstring, '
1779 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271780 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221781
1782
[email protected]2a8ac9c2011-10-19 17:20:441783def _CheckNoDEPSGIT(input_api, output_api):
1784 """Make sure .DEPS.git is never modified manually."""
1785 if any(f.LocalPath().endswith('.DEPS.git') for f in
1786 input_api.AffectedFiles()):
1787 return [output_api.PresubmitError(
1788 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1789 'automated system based on what\'s in DEPS and your changes will be\n'
1790 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501791 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1792 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441793 'for more information')]
1794 return []
1795
1796
tandriief664692014-09-23 14:51:471797def _CheckValidHostsInDEPS(input_api, output_api):
1798 """Checks that DEPS file deps are from allowed_hosts."""
1799 # Run only if DEPS file has been modified to annoy fewer bystanders.
1800 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1801 return []
1802 # Outsource work to gclient verify
1803 try:
John Budorickf20c0042019-04-25 23:23:401804 gclient_path = input_api.os_path.join(
1805 input_api.PresubmitLocalPath(),
1806 'third_party', 'depot_tools', 'gclient.py')
1807 input_api.subprocess.check_output(
1808 [input_api.python_executable, gclient_path, 'verify'],
1809 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471810 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201811 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471812 return [output_api.PresubmitError(
1813 'DEPS file must have only git dependencies.',
1814 long_text=error.output)]
1815
1816
Mario Sanchez Prada2472cab2019-09-18 10:58:311817def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1818 type_name, message):
1819 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1820
1821 Returns an string composed of the name of the file, the line number where the
1822 match has been found and the additional text passed as |message| in case the
1823 target type name matches the text inside the line passed as parameter.
1824 """
1825 matched = False
1826 if type_name[0:1] == '/':
1827 regex = type_name[1:]
1828 if input_api.re.search(regex, line):
1829 matched = True
1830 elif type_name in line:
1831 matched = True
1832
1833 result = []
1834 if matched:
1835 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1836 for message_line in message:
1837 result.append(' %s' % message_line)
1838
1839 return result
1840
1841
[email protected]127f18ec2012-06-16 05:05:591842def _CheckNoBannedFunctions(input_api, output_api):
1843 """Make sure that banned functions are not used."""
1844 warnings = []
1845 errors = []
1846
wnwenbdc444e2016-05-25 13:44:151847 def IsBlacklisted(affected_file, blacklist):
1848 local_path = affected_file.LocalPath()
1849 for item in blacklist:
1850 if input_api.re.match(item, local_path):
1851 return True
1852 return False
1853
Peter K. Lee6c03ccff2019-07-15 14:40:051854 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541855 local_path = affected_file.LocalPath()
1856 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1857 return False
1858 basename = input_api.os_path.basename(local_path)
1859 if 'ios' in basename.split('_'):
1860 return True
1861 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1862 if sep and 'ios' in local_path.split(sep):
1863 return True
1864 return False
1865
wnwenbdc444e2016-05-25 13:44:151866 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311867 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1868 func_name, message)
1869 if problems:
wnwenbdc444e2016-05-25 13:44:151870 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311871 errors.extend(problems)
1872 else:
1873 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151874
Eric Stevensona9a980972017-09-23 00:04:411875 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1876 for f in input_api.AffectedFiles(file_filter=file_filter):
1877 for line_num, line in f.ChangedContents():
1878 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1879 CheckForMatch(f, line_num, line, func_name, message, error)
1880
[email protected]127f18ec2012-06-16 05:05:591881 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1882 for f in input_api.AffectedFiles(file_filter=file_filter):
1883 for line_num, line in f.ChangedContents():
1884 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151885 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591886
Peter K. Lee6c03ccff2019-07-15 14:40:051887 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541888 for line_num, line in f.ChangedContents():
1889 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1890 CheckForMatch(f, line_num, line, func_name, message, error)
1891
Peter K. Lee6c03ccff2019-07-15 14:40:051892 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1893 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1894 for line_num, line in f.ChangedContents():
1895 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1896 CheckForMatch(f, line_num, line, func_name, message, error)
1897
[email protected]127f18ec2012-06-16 05:05:591898 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1899 for f in input_api.AffectedFiles(file_filter=file_filter):
1900 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491901 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491902 if IsBlacklisted(f, excluded_paths):
1903 continue
wnwenbdc444e2016-05-25 13:44:151904 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591905
1906 result = []
1907 if (warnings):
1908 result.append(output_api.PresubmitPromptWarning(
1909 'Banned functions were used.\n' + '\n'.join(warnings)))
1910 if (errors):
1911 result.append(output_api.PresubmitError(
1912 'Banned functions were used.\n' + '\n'.join(errors)))
1913 return result
1914
1915
Michael Thiessen44457642020-02-06 00:24:151916def _CheckAndroidNoBannedImports(input_api, output_api):
1917 """Make sure that banned java imports are not used."""
1918 errors = []
1919
1920 def IsException(path, exceptions):
1921 for exception in exceptions:
1922 if (path.startswith(exception)):
1923 return True
1924 return False
1925
1926 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1927 for f in input_api.AffectedFiles(file_filter=file_filter):
1928 for line_num, line in f.ChangedContents():
1929 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1930 if IsException(f.LocalPath(), exceptions):
1931 continue;
1932 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1933 'import ' + import_name, message)
1934 if problems:
1935 errors.extend(problems)
1936 result = []
1937 if (errors):
1938 result.append(output_api.PresubmitError(
1939 'Banned imports were used.\n' + '\n'.join(errors)))
1940 return result
1941
1942
Mario Sanchez Prada2472cab2019-09-18 10:58:311943def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1944 """Make sure that old Mojo types are not used."""
1945 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571946 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311947
Mario Sanchez Pradaaab91382019-12-19 08:57:091948 # For any path that is not an "ok" or an "error" path, a warning will be
1949 # raised if deprecated mojo types are found.
1950 ok_paths = ['components/arc']
1951 error_paths = ['third_party/blink', 'content']
1952
Mario Sanchez Prada2472cab2019-09-18 10:58:311953 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1954 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571955 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091956 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311957 continue
1958
1959 for line_num, line in f.ChangedContents():
1960 for func_name, message in _DEPRECATED_MOJO_TYPES:
1961 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1962 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571963
Mario Sanchez Prada2472cab2019-09-18 10:58:311964 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091965 # Raise errors inside |error_paths| and warnings everywhere else.
1966 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571967 errors.extend(problems)
1968 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311969 warnings.extend(problems)
1970
1971 result = []
1972 if (warnings):
1973 result.append(output_api.PresubmitPromptWarning(
1974 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571975 if (errors):
1976 result.append(output_api.PresubmitError(
1977 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311978 return result
1979
1980
[email protected]6c063c62012-07-11 19:11:061981def _CheckNoPragmaOnce(input_api, output_api):
1982 """Make sure that banned functions are not used."""
1983 files = []
1984 pattern = input_api.re.compile(r'^#pragma\s+once',
1985 input_api.re.MULTILINE)
1986 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1987 if not f.LocalPath().endswith('.h'):
1988 continue
1989 contents = input_api.ReadFile(f)
1990 if pattern.search(contents):
1991 files.append(f)
1992
1993 if files:
1994 return [output_api.PresubmitError(
1995 'Do not use #pragma once in header files.\n'
1996 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1997 files)]
1998 return []
1999
[email protected]127f18ec2012-06-16 05:05:592000
[email protected]e7479052012-09-19 00:26:122001def _CheckNoTrinaryTrueFalse(input_api, output_api):
2002 """Checks to make sure we don't introduce use of foo ? true : false."""
2003 problems = []
2004 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2005 for f in input_api.AffectedFiles():
2006 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2007 continue
2008
2009 for line_num, line in f.ChangedContents():
2010 if pattern.match(line):
2011 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2012
2013 if not problems:
2014 return []
2015 return [output_api.PresubmitPromptWarning(
2016 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2017 '\n'.join(problems))]
2018
2019
[email protected]55f9f382012-07-31 11:02:182020def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282021 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182022 change. Breaking - rules is an error, breaking ! rules is a
2023 warning.
2024 """
mohan.reddyf21db962014-10-16 12:26:472025 import sys
[email protected]55f9f382012-07-31 11:02:182026 # We need to wait until we have an input_api object and use this
2027 # roundabout construct to import checkdeps because this file is
2028 # eval-ed and thus doesn't have __file__.
2029 original_sys_path = sys.path
2030 try:
2031 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472032 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182033 import checkdeps
[email protected]55f9f382012-07-31 11:02:182034 from rules import Rule
2035 finally:
2036 # Restore sys.path to what it was before.
2037 sys.path = original_sys_path
2038
2039 added_includes = []
rhalavati08acd232017-04-03 07:23:282040 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242041 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182042 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062043 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502044 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082045 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062046 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502047 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082048 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062049 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502050 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082051 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182052
[email protected]26385172013-05-09 23:11:352053 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182054
2055 error_descriptions = []
2056 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282057 error_subjects = set()
2058 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182059 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2060 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082061 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182062 description_with_path = '%s\n %s' % (path, rule_description)
2063 if rule_type == Rule.DISALLOW:
2064 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282065 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182066 else:
2067 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282068 warning_subjects.add("#includes")
2069
2070 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2071 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082072 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282073 description_with_path = '%s\n %s' % (path, rule_description)
2074 if rule_type == Rule.DISALLOW:
2075 error_descriptions.append(description_with_path)
2076 error_subjects.add("imports")
2077 else:
2078 warning_descriptions.append(description_with_path)
2079 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182080
Jinsuk Kim5a092672017-10-24 22:42:242081 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022082 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082083 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242084 description_with_path = '%s\n %s' % (path, rule_description)
2085 if rule_type == Rule.DISALLOW:
2086 error_descriptions.append(description_with_path)
2087 error_subjects.add("imports")
2088 else:
2089 warning_descriptions.append(description_with_path)
2090 warning_subjects.add("imports")
2091
[email protected]55f9f382012-07-31 11:02:182092 results = []
2093 if error_descriptions:
2094 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282095 'You added one or more %s that violate checkdeps rules.'
2096 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182097 error_descriptions))
2098 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422099 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282100 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182101 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282102 '%s? See relevant DEPS file(s) for details and contacts.' %
2103 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182104 warning_descriptions))
2105 return results
2106
2107
[email protected]fbcafe5a2012-08-08 15:31:222108def _CheckFilePermissions(input_api, output_api):
2109 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152110 if input_api.platform == 'win32':
2111 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292112 checkperms_tool = input_api.os_path.join(
2113 input_api.PresubmitLocalPath(),
2114 'tools', 'checkperms', 'checkperms.py')
2115 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472116 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392117 with input_api.CreateTemporaryFile() as file_list:
2118 for f in input_api.AffectedFiles():
2119 # checkperms.py file/directory arguments must be relative to the
2120 # repository.
2121 file_list.write(f.LocalPath() + '\n')
2122 file_list.close()
2123 args += ['--file-list', file_list.name]
2124 try:
2125 input_api.subprocess.check_output(args)
2126 return []
2127 except input_api.subprocess.CalledProcessError as error:
2128 return [output_api.PresubmitError(
2129 'checkperms.py failed:',
2130 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222131
2132
robertocn832f5992017-01-04 19:01:302133def _CheckTeamTags(input_api, output_api):
2134 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2135 checkteamtags_tool = input_api.os_path.join(
2136 input_api.PresubmitLocalPath(),
2137 'tools', 'checkteamtags', 'checkteamtags.py')
2138 args = [input_api.python_executable, checkteamtags_tool,
2139 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222140 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302141 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2142 'OWNERS']
2143 try:
2144 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052145 warnings = input_api.subprocess.check_output(args + files).splitlines()
2146 if warnings:
2147 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302148 return []
2149 except input_api.subprocess.CalledProcessError as error:
2150 return [output_api.PresubmitError(
2151 'checkteamtags.py failed:',
2152 long_text=error.output)]
2153
2154
[email protected]c8278b32012-10-30 20:35:492155def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2156 """Makes sure we don't include ui/aura/window_property.h
2157 in header files.
2158 """
2159 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2160 errors = []
2161 for f in input_api.AffectedFiles():
2162 if not f.LocalPath().endswith('.h'):
2163 continue
2164 for line_num, line in f.ChangedContents():
2165 if pattern.match(line):
2166 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2167
2168 results = []
2169 if errors:
2170 results.append(output_api.PresubmitError(
2171 'Header files should not include ui/aura/window_property.h', errors))
2172 return results
2173
2174
[email protected]70ca77752012-11-20 03:45:032175def _CheckForVersionControlConflictsInFile(input_api, f):
2176 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2177 errors = []
2178 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162179 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232180 # First-level headers in markdown look a lot like version control
2181 # conflict markers. http://daringfireball.net/projects/markdown/basics
2182 continue
[email protected]70ca77752012-11-20 03:45:032183 if pattern.match(line):
2184 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2185 return errors
2186
2187
2188def _CheckForVersionControlConflicts(input_api, output_api):
2189 """Usually this is not intentional and will cause a compile failure."""
2190 errors = []
2191 for f in input_api.AffectedFiles():
2192 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2193
2194 results = []
2195 if errors:
2196 results.append(output_api.PresubmitError(
2197 'Version control conflict markers found, please resolve.', errors))
2198 return results
2199
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202200
estadee17314a02017-01-12 16:22:162201def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2202 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2203 errors = []
2204 for f in input_api.AffectedFiles():
2205 for line_num, line in f.ChangedContents():
2206 if pattern.search(line):
2207 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2208
2209 results = []
2210 if errors:
2211 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502212 'Found Google support URL addressed by answer number. Please replace '
2213 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162214 return results
2215
[email protected]70ca77752012-11-20 03:45:032216
[email protected]06e6d0ff2012-12-11 01:36:442217def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2218 def FilterFile(affected_file):
2219 """Filter function for use with input_api.AffectedSourceFiles,
2220 below. This filters out everything except non-test files from
2221 top-level directories that generally speaking should not hard-code
2222 service URLs (e.g. src/android_webview/, src/content/ and others).
2223 """
2224 return input_api.FilterSourceFile(
2225 affected_file,
Egor Paskoce145c42018-09-28 19:31:042226 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442227 black_list=(_EXCLUDED_PATHS +
2228 _TEST_CODE_EXCLUDED_PATHS +
2229 input_api.DEFAULT_BLACK_LIST))
2230
reillyi38965732015-11-16 18:27:332231 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2232 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462233 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2234 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442235 problems = [] # items are (filename, line_number, line)
2236 for f in input_api.AffectedSourceFiles(FilterFile):
2237 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462238 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442239 problems.append((f.LocalPath(), line_num, line))
2240
2241 if problems:
[email protected]f7051d52013-04-02 18:31:422242 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442243 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582244 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442245 [' %s:%d: %s' % (
2246 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032247 else:
2248 return []
[email protected]06e6d0ff2012-12-11 01:36:442249
2250
James Cook6b6597c2019-11-06 22:05:292251def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2252 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2253 def FileFilter(affected_file):
2254 """Includes directories known to be Chrome OS only."""
2255 return input_api.FilterSourceFile(
2256 affected_file,
2257 white_list=('^ash/',
2258 '^chromeos/', # Top-level src/chromeos.
2259 '/chromeos/', # Any path component.
2260 '^components/arc',
2261 '^components/exo'),
2262 black_list=(input_api.DEFAULT_BLACK_LIST))
2263
2264 prefs = []
2265 priority_prefs = []
2266 for f in input_api.AffectedFiles(file_filter=FileFilter):
2267 for line_num, line in f.ChangedContents():
2268 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2269 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2270 prefs.append(' %s' % line)
2271 if input_api.re.search(
2272 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2273 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2274 priority_prefs.append(' %s' % line)
2275
2276 results = []
2277 if (prefs):
2278 results.append(output_api.PresubmitPromptWarning(
2279 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2280 'by browser sync settings. If these prefs should be controlled by OS '
2281 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2282 if (priority_prefs):
2283 results.append(output_api.PresubmitPromptWarning(
2284 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2285 'controlled by browser sync settings. If these prefs should be '
2286 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2287 'instead.\n' + '\n'.join(prefs)))
2288 return results
2289
2290
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492291# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272292def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2293 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312294 The native_client_sdk directory is excluded because it has auto-generated PNG
2295 files for documentation.
[email protected]d2530012013-01-25 16:39:272296 """
[email protected]d2530012013-01-25 16:39:272297 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492298 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042299 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312300 file_filter = lambda f: input_api.FilterSourceFile(
2301 f, white_list=white_list, black_list=black_list)
2302 for f in input_api.AffectedFiles(include_deletes=False,
2303 file_filter=file_filter):
2304 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272305
2306 results = []
2307 if errors:
2308 results.append(output_api.PresubmitError(
2309 'The name of PNG files should not have abbreviations. \n'
2310 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2311 'Contact [email protected] if you have questions.', errors))
2312 return results
2313
2314
Daniel Cheng4dcdb6b2017-04-13 08:30:172315def _ExtractAddRulesFromParsedDeps(parsed_deps):
2316 """Extract the rules that add dependencies from a parsed DEPS file.
2317
2318 Args:
2319 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2320 add_rules = set()
2321 add_rules.update([
2322 rule[1:] for rule in parsed_deps.get('include_rules', [])
2323 if rule.startswith('+') or rule.startswith('!')
2324 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502325 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172326 {}).iteritems():
2327 add_rules.update([
2328 rule[1:] for rule in rules
2329 if rule.startswith('+') or rule.startswith('!')
2330 ])
2331 return add_rules
2332
2333
2334def _ParseDeps(contents):
2335 """Simple helper for parsing DEPS files."""
2336 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172337 class _VarImpl:
2338
2339 def __init__(self, local_scope):
2340 self._local_scope = local_scope
2341
2342 def Lookup(self, var_name):
2343 """Implements the Var syntax."""
2344 try:
2345 return self._local_scope['vars'][var_name]
2346 except KeyError:
2347 raise Exception('Var is not defined: %s' % var_name)
2348
2349 local_scope = {}
2350 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172351 'Var': _VarImpl(local_scope).Lookup,
2352 }
2353 exec contents in global_scope, local_scope
2354 return local_scope
2355
2356
2357def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082358 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412359 a set of DEPS entries that we should look up.
2360
2361 For a directory (rather than a specific filename) we fake a path to
2362 a specific filename by adding /DEPS. This is chosen as a file that
2363 will seldom or never be subject to per-file include_rules.
2364 """
[email protected]2b438d62013-11-14 17:54:142365 # We ignore deps entries on auto-generated directories.
2366 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082367
Daniel Cheng4dcdb6b2017-04-13 08:30:172368 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2369 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2370
2371 added_deps = new_deps.difference(old_deps)
2372
[email protected]2b438d62013-11-14 17:54:142373 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172374 for added_dep in added_deps:
2375 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2376 continue
2377 # Assume that a rule that ends in .h is a rule for a specific file.
2378 if added_dep.endswith('.h'):
2379 results.add(added_dep)
2380 else:
2381 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082382 return results
2383
2384
[email protected]e871964c2013-05-13 14:14:552385def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2386 """When a dependency prefixed with + is added to a DEPS file, we
2387 want to make sure that the change is reviewed by an OWNER of the
2388 target file or directory, to avoid layering violations from being
2389 introduced. This check verifies that this happens.
2390 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172391 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242392
2393 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492394 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242395 for f in input_api.AffectedFiles(include_deletes=False,
2396 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552397 filename = input_api.os_path.basename(f.LocalPath())
2398 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172399 virtual_depended_on_files.update(_CalculateAddedDeps(
2400 input_api.os_path,
2401 '\n'.join(f.OldContents()),
2402 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552403
[email protected]e871964c2013-05-13 14:14:552404 if not virtual_depended_on_files:
2405 return []
2406
2407 if input_api.is_committing:
2408 if input_api.tbr:
2409 return [output_api.PresubmitNotifyResult(
2410 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272411 if input_api.dry_run:
2412 return [output_api.PresubmitNotifyResult(
2413 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552414 if not input_api.change.issue:
2415 return [output_api.PresubmitError(
2416 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402417 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552418 output = output_api.PresubmitError
2419 else:
2420 output = output_api.PresubmitNotifyResult
2421
2422 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502423 owner_email, reviewers = (
2424 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2425 input_api,
2426 owners_db.email_regexp,
2427 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552428
2429 owner_email = owner_email or input_api.change.author_email
2430
[email protected]de4f7d22013-05-23 14:27:462431 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512432 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462433 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552434 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2435 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412436
2437 # We strip the /DEPS part that was added by
2438 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2439 # directory.
2440 def StripDeps(path):
2441 start_deps = path.rfind('/DEPS')
2442 if start_deps != -1:
2443 return path[:start_deps]
2444 else:
2445 return path
2446 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552447 for path in missing_files]
2448
2449 if unapproved_dependencies:
2450 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152451 output('You need LGTM from owners of depends-on paths in DEPS that were '
2452 'modified in this CL:\n %s' %
2453 '\n '.join(sorted(unapproved_dependencies)))]
2454 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2455 output_list.append(output(
2456 'Suggested missing target path OWNERS:\n %s' %
2457 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552458 return output_list
2459
2460 return []
2461
2462
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492463# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402464def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492465 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402466 black_list = (_EXCLUDED_PATHS +
2467 _TEST_CODE_EXCLUDED_PATHS +
2468 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042469 (r"^base[\\/]logging\.h$",
2470 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222471 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042472 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2473 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2474 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122475 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182476 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152477 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032478 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152479 r"^chrome[\\/]chrome_cleaner[\\/].*",
2480 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2481 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042482 r"^chromecast[\\/]",
2483 r"^cloud_print[\\/]",
2484 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482485 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042486 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312487 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042488 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462489 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042490 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462491 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042492 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252493 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042494 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2495 r"^courgette[\\/]courgette_tool\.cc$",
2496 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272497 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002498 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332499 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042500 r"^ipc[\\/]ipc_logging\.cc$",
2501 r"^native_client_sdk[\\/]",
2502 r"^remoting[\\/]base[\\/]logging\.h$",
2503 r"^remoting[\\/]host[\\/].*",
2504 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062505 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332506 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042507 r"^tools[\\/]",
2508 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2509 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332510 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402511 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492512 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402513
thomasanderson625d3932017-03-29 07:16:582514 log_info = set([])
2515 printf = set([])
[email protected]85218562013-11-22 07:41:402516
2517 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582518 for _, line in f.ChangedContents():
2519 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2520 log_info.add(f.LocalPath())
2521 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2522 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372523
thomasanderson625d3932017-03-29 07:16:582524 if input_api.re.search(r"\bprintf\(", line):
2525 printf.add(f.LocalPath())
2526 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2527 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402528
2529 if log_info:
2530 return [output_api.PresubmitError(
2531 'These files spam the console log with LOG(INFO):',
2532 items=log_info)]
2533 if printf:
2534 return [output_api.PresubmitError(
2535 'These files spam the console log with printf/fprintf:',
2536 items=printf)]
2537 return []
2538
2539
[email protected]49aa76a2013-12-04 06:59:162540def _CheckForAnonymousVariables(input_api, output_api):
2541 """These types are all expected to hold locks while in scope and
2542 so should never be anonymous (which causes them to be immediately
2543 destroyed)."""
2544 they_who_must_be_named = [
2545 'base::AutoLock',
2546 'base::AutoReset',
2547 'base::AutoUnlock',
2548 'SkAutoAlphaRestore',
2549 'SkAutoBitmapShaderInstall',
2550 'SkAutoBlitterChoose',
2551 'SkAutoBounderCommit',
2552 'SkAutoCallProc',
2553 'SkAutoCanvasRestore',
2554 'SkAutoCommentBlock',
2555 'SkAutoDescriptor',
2556 'SkAutoDisableDirectionCheck',
2557 'SkAutoDisableOvalCheck',
2558 'SkAutoFree',
2559 'SkAutoGlyphCache',
2560 'SkAutoHDC',
2561 'SkAutoLockColors',
2562 'SkAutoLockPixels',
2563 'SkAutoMalloc',
2564 'SkAutoMaskFreeImage',
2565 'SkAutoMutexAcquire',
2566 'SkAutoPathBoundsUpdate',
2567 'SkAutoPDFRelease',
2568 'SkAutoRasterClipValidate',
2569 'SkAutoRef',
2570 'SkAutoTime',
2571 'SkAutoTrace',
2572 'SkAutoUnref',
2573 ]
2574 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2575 # bad: base::AutoLock(lock.get());
2576 # not bad: base::AutoLock lock(lock.get());
2577 bad_pattern = input_api.re.compile(anonymous)
2578 # good: new base::AutoLock(lock.get())
2579 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2580 errors = []
2581
2582 for f in input_api.AffectedFiles():
2583 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2584 continue
2585 for linenum, line in f.ChangedContents():
2586 if bad_pattern.search(line) and not good_pattern.search(line):
2587 errors.append('%s:%d' % (f.LocalPath(), linenum))
2588
2589 if errors:
2590 return [output_api.PresubmitError(
2591 'These lines create anonymous variables that need to be named:',
2592 items=errors)]
2593 return []
2594
2595
Peter Kasting4844e46e2018-02-23 07:27:102596def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532597 # Returns whether |template_str| is of the form <T, U...> for some types T
2598 # and U. Assumes that |template_str| is already in the form <...>.
2599 def HasMoreThanOneArg(template_str):
2600 # Level of <...> nesting.
2601 nesting = 0
2602 for c in template_str:
2603 if c == '<':
2604 nesting += 1
2605 elif c == '>':
2606 nesting -= 1
2607 elif c == ',' and nesting == 1:
2608 return True
2609 return False
2610
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492611 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102612 sources = lambda affected_file: input_api.FilterSourceFile(
2613 affected_file,
2614 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2615 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492616 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552617
2618 # Pattern to capture a single "<...>" block of template arguments. It can
2619 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2620 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2621 # latter would likely require counting that < and > match, which is not
2622 # expressible in regular languages. Should the need arise, one can introduce
2623 # limited counting (matching up to a total number of nesting depth), which
2624 # should cover all practical cases for already a low nesting limit.
2625 template_arg_pattern = (
2626 r'<[^>]*' # Opening block of <.
2627 r'>([^<]*>)?') # Closing block of >.
2628 # Prefix expressing that whatever follows is not already inside a <...>
2629 # block.
2630 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102631 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552632 not_inside_template_arg_pattern
2633 + r'\bstd::unique_ptr'
2634 + template_arg_pattern
2635 + r'\(\)')
2636
2637 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2638 template_arg_no_array_pattern = (
2639 r'<[^>]*[^]]' # Opening block of <.
2640 r'>([^(<]*[^]]>)?') # Closing block of >.
2641 # Prefix saying that what follows is the start of an expression.
2642 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2643 # Suffix saying that what follows are call parentheses with a non-empty list
2644 # of arguments.
2645 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532646 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552647 return_construct_pattern = input_api.re.compile(
2648 start_of_expr_pattern
2649 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532650 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552651 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532652 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552653 + nonempty_arg_list_pattern)
2654
Vaclav Brozek851d9602018-04-04 16:13:052655 problems_constructor = []
2656 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102657 for f in input_api.AffectedSourceFiles(sources):
2658 for line_number, line in f.ChangedContents():
2659 # Disallow:
2660 # return std::unique_ptr<T>(foo);
2661 # bar = std::unique_ptr<T>(foo);
2662 # But allow:
2663 # return std::unique_ptr<T[]>(foo);
2664 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532665 # And also allow cases when the second template argument is present. Those
2666 # cases cannot be handled by std::make_unique:
2667 # return std::unique_ptr<T, U>(foo);
2668 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052669 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532670 return_construct_result = return_construct_pattern.search(line)
2671 if return_construct_result and not HasMoreThanOneArg(
2672 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052673 problems_constructor.append(
2674 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102675 # Disallow:
2676 # std::unique_ptr<T>()
2677 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052678 problems_nullptr.append(
2679 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2680
2681 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162682 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052683 errors.append(output_api.PresubmitError(
2684 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162685 problems_nullptr))
2686 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052687 errors.append(output_api.PresubmitError(
2688 'The following files use explicit std::unique_ptr constructor.'
2689 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162690 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102691 return errors
2692
2693
[email protected]999261d2014-03-03 20:08:082694def _CheckUserActionUpdate(input_api, output_api):
2695 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522696 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082697 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522698 # If actions.xml is already included in the changelist, the PRESUBMIT
2699 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082700 return []
2701
[email protected]999261d2014-03-03 20:08:082702 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2703 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522704 current_actions = None
[email protected]999261d2014-03-03 20:08:082705 for f in input_api.AffectedFiles(file_filter=file_filter):
2706 for line_num, line in f.ChangedContents():
2707 match = input_api.re.search(action_re, line)
2708 if match:
[email protected]2f92dec2014-03-07 19:21:522709 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2710 # loaded only once.
2711 if not current_actions:
2712 with open('tools/metrics/actions/actions.xml') as actions_f:
2713 current_actions = actions_f.read()
2714 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082715 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522716 action = 'name="{0}"'.format(action_name)
2717 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082718 return [output_api.PresubmitPromptWarning(
2719 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522720 'tools/metrics/actions/actions.xml. Please run '
2721 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082722 % (f.LocalPath(), line_num, action_name))]
2723 return []
2724
2725
Daniel Cheng13ca61a882017-08-25 15:11:252726def _ImportJSONCommentEater(input_api):
2727 import sys
2728 sys.path = sys.path + [input_api.os_path.join(
2729 input_api.PresubmitLocalPath(),
2730 'tools', 'json_comment_eater')]
2731 import json_comment_eater
2732 return json_comment_eater
2733
2734
[email protected]99171a92014-06-03 08:44:472735def _GetJSONParseError(input_api, filename, eat_comments=True):
2736 try:
2737 contents = input_api.ReadFile(filename)
2738 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252739 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132740 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472741
2742 input_api.json.loads(contents)
2743 except ValueError as e:
2744 return e
2745 return None
2746
2747
2748def _GetIDLParseError(input_api, filename):
2749 try:
2750 contents = input_api.ReadFile(filename)
2751 idl_schema = input_api.os_path.join(
2752 input_api.PresubmitLocalPath(),
2753 'tools', 'json_schema_compiler', 'idl_schema.py')
2754 process = input_api.subprocess.Popen(
2755 [input_api.python_executable, idl_schema],
2756 stdin=input_api.subprocess.PIPE,
2757 stdout=input_api.subprocess.PIPE,
2758 stderr=input_api.subprocess.PIPE,
2759 universal_newlines=True)
2760 (_, error) = process.communicate(input=contents)
2761 return error or None
2762 except ValueError as e:
2763 return e
2764
2765
2766def _CheckParseErrors(input_api, output_api):
2767 """Check that IDL and JSON files do not contain syntax errors."""
2768 actions = {
2769 '.idl': _GetIDLParseError,
2770 '.json': _GetJSONParseError,
2771 }
[email protected]99171a92014-06-03 08:44:472772 # Most JSON files are preprocessed and support comments, but these do not.
2773 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042774 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472775 ]
2776 # Only run IDL checker on files in these directories.
2777 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042778 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2779 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472780 ]
2781
2782 def get_action(affected_file):
2783 filename = affected_file.LocalPath()
2784 return actions.get(input_api.os_path.splitext(filename)[1])
2785
[email protected]99171a92014-06-03 08:44:472786 def FilterFile(affected_file):
2787 action = get_action(affected_file)
2788 if not action:
2789 return False
2790 path = affected_file.LocalPath()
2791
Sean Kau46e29bc2017-08-28 16:31:162792 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472793 return False
2794
2795 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162796 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472797 return False
2798 return True
2799
2800 results = []
2801 for affected_file in input_api.AffectedFiles(
2802 file_filter=FilterFile, include_deletes=False):
2803 action = get_action(affected_file)
2804 kwargs = {}
2805 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162806 _MatchesFile(input_api, json_no_comments_patterns,
2807 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472808 kwargs['eat_comments'] = False
2809 parse_error = action(input_api,
2810 affected_file.AbsoluteLocalPath(),
2811 **kwargs)
2812 if parse_error:
2813 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2814 (affected_file.LocalPath(), parse_error)))
2815 return results
2816
2817
[email protected]760deea2013-12-10 19:33:492818def _CheckJavaStyle(input_api, output_api):
2819 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472820 import sys
[email protected]760deea2013-12-10 19:33:492821 original_sys_path = sys.path
2822 try:
2823 sys.path = sys.path + [input_api.os_path.join(
2824 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2825 import checkstyle
2826 finally:
2827 # Restore sys.path to what it was before.
2828 sys.path = original_sys_path
2829
2830 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092831 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512832 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492833
2834
Nate Fischerdfd9812e2019-07-18 22:03:002835def _CheckPythonDevilInit(input_api, output_api):
2836 """Checks to make sure devil is initialized correctly in python scripts."""
2837 script_common_initialize_pattern = input_api.re.compile(
2838 r'script_common\.InitializeEnvironment\(')
2839 devil_env_config_initialize = input_api.re.compile(
2840 r'devil_env\.config\.Initialize\(')
2841
2842 errors = []
2843
2844 sources = lambda affected_file: input_api.FilterSourceFile(
2845 affected_file,
2846 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2847 (r'^build[\\/]android[\\/]devil_chromium\.py',
2848 r'^third_party[\\/].*',)),
2849 white_list=[r'.*\.py$'])
2850
2851 for f in input_api.AffectedSourceFiles(sources):
2852 for line_num, line in f.ChangedContents():
2853 if (script_common_initialize_pattern.search(line) or
2854 devil_env_config_initialize.search(line)):
2855 errors.append("%s:%d" % (f.LocalPath(), line_num))
2856
2857 results = []
2858
2859 if errors:
2860 results.append(output_api.PresubmitError(
2861 'Devil initialization should always be done using '
2862 'devil_chromium.Initialize() in the chromium project, to use better '
2863 'defaults for dependencies (ex. up-to-date version of adb).',
2864 errors))
2865
2866 return results
2867
2868
Sean Kau46e29bc2017-08-28 16:31:162869def _MatchesFile(input_api, patterns, path):
2870 for pattern in patterns:
2871 if input_api.re.search(pattern, path):
2872 return True
2873 return False
2874
2875
Daniel Cheng7052cdf2017-11-21 19:23:292876def _GetOwnersFilesToCheckForIpcOwners(input_api):
2877 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172878
Daniel Cheng7052cdf2017-11-21 19:23:292879 Returns:
2880 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2881 contain to cover IPC-related files with noparent reviewer rules.
2882 """
2883 # Whether or not a file affects IPC is (mostly) determined by a simple list
2884 # of filename patterns.
dchenge07de812016-06-20 19:27:172885 file_patterns = [
palmerb19a0932017-01-24 04:00:312886 # Legacy IPC:
dchenge07de812016-06-20 19:27:172887 '*_messages.cc',
2888 '*_messages*.h',
2889 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312890 # Mojo IPC:
dchenge07de812016-06-20 19:27:172891 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472892 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172893 '*_struct_traits*.*',
2894 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312895 '*.typemap',
2896 # Android native IPC:
2897 '*.aidl',
2898 # Blink uses a different file naming convention:
2899 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472900 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172901 '*StructTraits*.*',
2902 '*TypeConverter*.*',
2903 ]
2904
scottmg7a6ed5ba2016-11-04 18:22:042905 # These third_party directories do not contain IPCs, but contain files
2906 # matching the above patterns, which trigger false positives.
2907 exclude_paths = [
2908 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162909 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232910 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292911 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542912 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162913 # These files are just used to communicate between class loaders running
2914 # in the same process.
2915 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572916 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2917
scottmg7a6ed5ba2016-11-04 18:22:042918 ]
2919
dchenge07de812016-06-20 19:27:172920 # Dictionary mapping an OWNERS file path to Patterns.
2921 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2922 # rules ) to a PatternEntry.
2923 # PatternEntry is a dictionary with two keys:
2924 # - 'files': the files that are matched by this pattern
2925 # - 'rules': the per-file rules needed for this pattern
2926 # For example, if we expect OWNERS file to contain rules for *.mojom and
2927 # *_struct_traits*.*, Patterns might look like this:
2928 # {
2929 # '*.mojom': {
2930 # 'files': ...,
2931 # 'rules': [
2932 # 'per-file *.mojom=set noparent',
2933 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2934 # ],
2935 # },
2936 # '*_struct_traits*.*': {
2937 # 'files': ...,
2938 # 'rules': [
2939 # 'per-file *_struct_traits*.*=set noparent',
2940 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2941 # ],
2942 # },
2943 # }
2944 to_check = {}
2945
Daniel Cheng13ca61a882017-08-25 15:11:252946 def AddPatternToCheck(input_file, pattern):
2947 owners_file = input_api.os_path.join(
2948 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2949 if owners_file not in to_check:
2950 to_check[owners_file] = {}
2951 if pattern not in to_check[owners_file]:
2952 to_check[owners_file][pattern] = {
2953 'files': [],
2954 'rules': [
2955 'per-file %s=set noparent' % pattern,
2956 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2957 ]
2958 }
Vaclav Brozekd5de76a2018-03-17 07:57:502959 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252960
dchenge07de812016-06-20 19:27:172961 # Iterate through the affected files to see what we actually need to check
2962 # for. We should only nag patch authors about per-file rules if a file in that
2963 # directory would match that pattern. If a directory only contains *.mojom
2964 # files and no *_messages*.h files, we should only nag about rules for
2965 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252966 for f in input_api.AffectedFiles(include_deletes=False):
2967 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362968 # affected files for .json, .cc, and .h files which look like they contain
2969 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162970 if (f.LocalPath().endswith('.json') and
2971 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2972 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252973 json_comment_eater = _ImportJSONCommentEater(input_api)
2974 mostly_json_lines = '\n'.join(f.NewContents())
2975 # Comments aren't allowed in strict JSON, so filter them out.
2976 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432977 try:
2978 json_content = input_api.json.loads(json_lines)
2979 except:
2980 # There's another PRESUBMIT check that already verifies that JSON files
2981 # are not invalid, so no need to emit another warning here.
2982 continue
Daniel Cheng13ca61a882017-08-25 15:11:252983 if 'interface_provider_specs' in json_content:
2984 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362985 else:
2986 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2987 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2988 if (manifest_pattern.search(f.LocalPath()) and not
2989 test_manifest_pattern.search(f.LocalPath())):
2990 # We expect all actual service manifest files to contain at least one
2991 # qualified reference to service_manager::Manifest.
2992 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2993 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172994 for pattern in file_patterns:
2995 if input_api.fnmatch.fnmatch(
2996 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042997 skip = False
2998 for exclude in exclude_paths:
2999 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
3000 skip = True
3001 break
3002 if skip:
3003 continue
Daniel Cheng13ca61a882017-08-25 15:11:253004 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:173005 break
3006
Daniel Cheng7052cdf2017-11-21 19:23:293007 return to_check
3008
3009
3010def _CheckIpcOwners(input_api, output_api):
3011 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3012 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
3013
3014 if to_check:
3015 # If there are any OWNERS files to check, there are IPC-related changes in
3016 # this CL. Auto-CC the review list.
3017 output_api.AppendCC('[email protected]')
3018
3019 # Go through the OWNERS files to check, filtering out rules that are already
3020 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173021 for owners_file, patterns in to_check.iteritems():
3022 try:
3023 with file(owners_file) as f:
3024 lines = set(f.read().splitlines())
3025 for entry in patterns.itervalues():
3026 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3027 ]
3028 except IOError:
3029 # No OWNERS file, so all the rules are definitely missing.
3030 continue
3031
3032 # All the remaining lines weren't found in OWNERS files, so emit an error.
3033 errors = []
3034 for owners_file, patterns in to_check.iteritems():
3035 missing_lines = []
3036 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503037 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173038 missing_lines.extend(entry['rules'])
3039 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3040 if missing_lines:
3041 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053042 'Because of the presence of files:\n%s\n\n'
3043 '%s needs the following %d lines added:\n\n%s' %
3044 ('\n'.join(files), owners_file, len(missing_lines),
3045 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173046
3047 results = []
3048 if errors:
vabrf5ce3bf92016-07-11 14:52:413049 if input_api.is_committing:
3050 output = output_api.PresubmitError
3051 else:
3052 output = output_api.PresubmitPromptWarning
3053 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593054 'Found OWNERS files that need to be updated for IPC security ' +
3055 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173056 long_text='\n\n'.join(errors)))
3057
3058 return results
3059
3060
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263061def _CheckSetNoParent(input_api, output_api):
3062 """Checks that set noparent is only used together with an OWNERS file in
3063 //build/OWNERS.setnoparent (see also
3064 //docs/code_reviews.md#owners-files-details)
3065 """
3066 errors = []
3067
3068 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3069 allowed_owners_files = set()
3070 with open(allowed_owners_files_file, 'r') as f:
3071 for line in f:
3072 line = line.strip()
3073 if not line or line.startswith('#'):
3074 continue
3075 allowed_owners_files.add(line)
3076
3077 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3078
3079 for f in input_api.AffectedFiles(include_deletes=False):
3080 if not f.LocalPath().endswith('OWNERS'):
3081 continue
3082
3083 found_owners_files = set()
3084 found_set_noparent_lines = dict()
3085
3086 # Parse the OWNERS file.
3087 for lineno, line in enumerate(f.NewContents(), 1):
3088 line = line.strip()
3089 if line.startswith('set noparent'):
3090 found_set_noparent_lines[''] = lineno
3091 if line.startswith('file://'):
3092 if line in allowed_owners_files:
3093 found_owners_files.add('')
3094 if line.startswith('per-file'):
3095 match = per_file_pattern.match(line)
3096 if match:
3097 glob = match.group(1).strip()
3098 directive = match.group(2).strip()
3099 if directive == 'set noparent':
3100 found_set_noparent_lines[glob] = lineno
3101 if directive.startswith('file://'):
3102 if directive in allowed_owners_files:
3103 found_owners_files.add(glob)
3104
3105 # Check that every set noparent line has a corresponding file:// line
3106 # listed in build/OWNERS.setnoparent.
3107 for set_noparent_line in found_set_noparent_lines:
3108 if set_noparent_line in found_owners_files:
3109 continue
3110 errors.append(' %s:%d' % (f.LocalPath(),
3111 found_set_noparent_lines[set_noparent_line]))
3112
3113 results = []
3114 if errors:
3115 if input_api.is_committing:
3116 output = output_api.PresubmitError
3117 else:
3118 output = output_api.PresubmitPromptWarning
3119 results.append(output(
3120 'Found the following "set noparent" restrictions in OWNERS files that '
3121 'do not include owners from build/OWNERS.setnoparent:',
3122 long_text='\n\n'.join(errors)))
3123 return results
3124
3125
jbriance9e12f162016-11-25 07:57:503126def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313127 """Checks that added or removed lines in non third party affected
3128 header files do not lead to new useless class or struct forward
3129 declaration.
jbriance9e12f162016-11-25 07:57:503130 """
3131 results = []
3132 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3133 input_api.re.MULTILINE)
3134 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3135 input_api.re.MULTILINE)
3136 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313137 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193138 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493139 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313140 continue
3141
jbriance9e12f162016-11-25 07:57:503142 if not f.LocalPath().endswith('.h'):
3143 continue
3144
3145 contents = input_api.ReadFile(f)
3146 fwd_decls = input_api.re.findall(class_pattern, contents)
3147 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3148
3149 useless_fwd_decls = []
3150 for decl in fwd_decls:
3151 count = sum(1 for _ in input_api.re.finditer(
3152 r'\b%s\b' % input_api.re.escape(decl), contents))
3153 if count == 1:
3154 useless_fwd_decls.append(decl)
3155
3156 if not useless_fwd_decls:
3157 continue
3158
3159 for line in f.GenerateScmDiff().splitlines():
3160 if (line.startswith('-') and not line.startswith('--') or
3161 line.startswith('+') and not line.startswith('++')):
3162 for decl in useless_fwd_decls:
3163 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3164 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243165 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503166 (f.LocalPath(), decl)))
3167 useless_fwd_decls.remove(decl)
3168
3169 return results
3170
Jinsong Fan91ebbbd2019-04-16 14:57:173171def _CheckAndroidDebuggableBuild(input_api, output_api):
3172 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3173 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3174 this is a debuggable build of Android.
3175 """
3176 build_type_check_pattern = input_api.re.compile(
3177 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3178
3179 errors = []
3180
3181 sources = lambda affected_file: input_api.FilterSourceFile(
3182 affected_file,
3183 black_list=(_EXCLUDED_PATHS +
3184 _TEST_CODE_EXCLUDED_PATHS +
3185 input_api.DEFAULT_BLACK_LIST +
3186 (r"^android_webview[\\/]support_library[\\/]"
3187 "boundary_interfaces[\\/]",
3188 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3189 r'^third_party[\\/].*',
3190 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3191 r"webview[\\/]chromium[\\/]License.*",)),
3192 white_list=[r'.*\.java$'])
3193
3194 for f in input_api.AffectedSourceFiles(sources):
3195 for line_num, line in f.ChangedContents():
3196 if build_type_check_pattern.search(line):
3197 errors.append("%s:%d" % (f.LocalPath(), line_num))
3198
3199 results = []
3200
3201 if errors:
3202 results.append(output_api.PresubmitPromptWarning(
3203 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3204 ' Please use BuildInfo.isDebugAndroid() instead.',
3205 errors))
3206
3207 return results
jbriance9e12f162016-11-25 07:57:503208
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493209# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293210def _CheckAndroidToastUsage(input_api, output_api):
3211 """Checks that code uses org.chromium.ui.widget.Toast instead of
3212 android.widget.Toast (Chromium Toast doesn't force hardware
3213 acceleration on low-end devices, saving memory).
3214 """
3215 toast_import_pattern = input_api.re.compile(
3216 r'^import android\.widget\.Toast;$')
3217
3218 errors = []
3219
3220 sources = lambda affected_file: input_api.FilterSourceFile(
3221 affected_file,
3222 black_list=(_EXCLUDED_PATHS +
3223 _TEST_CODE_EXCLUDED_PATHS +
3224 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043225 (r'^chromecast[\\/].*',
3226 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493227 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293228
3229 for f in input_api.AffectedSourceFiles(sources):
3230 for line_num, line in f.ChangedContents():
3231 if toast_import_pattern.search(line):
3232 errors.append("%s:%d" % (f.LocalPath(), line_num))
3233
3234 results = []
3235
3236 if errors:
3237 results.append(output_api.PresubmitError(
3238 'android.widget.Toast usage is detected. Android toasts use hardware'
3239 ' acceleration, and can be\ncostly on low-end devices. Please use'
3240 ' org.chromium.ui.widget.Toast instead.\n'
3241 'Contact [email protected] if you have any questions.',
3242 errors))
3243
3244 return results
3245
3246
dgnaa68d5e2015-06-10 10:08:223247def _CheckAndroidCrLogUsage(input_api, output_api):
3248 """Checks that new logs using org.chromium.base.Log:
3249 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513250 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223251 """
pkotwicza1dd0b002016-05-16 14:41:043252
torne89540622017-03-24 19:41:303253 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043254 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303255 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043256 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303257 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043258 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3259 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093260 # The customtabs_benchmark is a small app that does not depend on Chromium
3261 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043262 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043263 ]
3264
dgnaa68d5e2015-06-10 10:08:223265 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123266 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3267 class_in_base_pattern = input_api.re.compile(
3268 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3269 has_some_log_import_pattern = input_api.re.compile(
3270 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223271 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
Tomasz Śniatowski3ae2f102020-03-23 15:35:553272 log_call_pattern = input_api.re.compile(r'\bLog\.\w\((?P<tag>\"?\w+)')
dgnaa68d5e2015-06-10 10:08:223273 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463274 r'static final String TAG = "(?P<name>(.*))"')
Tomasz Śniatowski3ae2f102020-03-23 15:35:553275 rough_log_decl_pattern = input_api.re.compile(r'\bString TAG\s*=')
dgnaa68d5e2015-06-10 10:08:223276
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463277 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493278 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043279 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123280
dgnaa68d5e2015-06-10 10:08:223281 tag_decl_errors = []
3282 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123283 tag_errors = []
dgn38736db2015-09-18 19:20:513284 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123285 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223286
3287 for f in input_api.AffectedSourceFiles(sources):
3288 file_content = input_api.ReadFile(f)
3289 has_modified_logs = False
dgnaa68d5e2015-06-10 10:08:223290 # Per line checks
dgn87d9fb62015-06-12 09:15:123291 if (cr_log_import_pattern.search(file_content) or
3292 (class_in_base_pattern.search(file_content) and
3293 not has_some_log_import_pattern.search(file_content))):
3294 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223295 for line_num, line in f.ChangedContents():
Tomasz Śniatowski3ae2f102020-03-23 15:35:553296 if rough_log_decl_pattern.search(line):
3297 has_modified_logs = True
dgnaa68d5e2015-06-10 10:08:223298
3299 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123300 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223301 if match:
3302 has_modified_logs = True
3303
3304 # Make sure it uses "TAG"
3305 if not match.group('tag') == 'TAG':
3306 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123307 else:
3308 # Report non cr Log function calls in changed lines
3309 for line_num, line in f.ChangedContents():
3310 if log_call_pattern.search(line):
3311 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223312
3313 # Per file checks
3314 if has_modified_logs:
3315 # Make sure the tag is using the "cr" prefix and is not too long
3316 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513317 tag_name = match.group('name') if match else None
3318 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223319 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513320 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223321 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513322 elif '.' in tag_name:
3323 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223324
3325 results = []
3326 if tag_decl_errors:
3327 results.append(output_api.PresubmitPromptWarning(
3328 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513329 '"private static final String TAG = "<package tag>".\n'
3330 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223331 tag_decl_errors))
3332
3333 if tag_length_errors:
3334 results.append(output_api.PresubmitError(
3335 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513336 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223337 tag_length_errors))
3338
3339 if tag_errors:
3340 results.append(output_api.PresubmitPromptWarning(
3341 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3342 tag_errors))
3343
dgn87d9fb62015-06-12 09:15:123344 if util_log_errors:
dgn4401aa52015-04-29 16:26:173345 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123346 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3347 util_log_errors))
3348
dgn38736db2015-09-18 19:20:513349 if tag_with_dot_errors:
3350 results.append(output_api.PresubmitPromptWarning(
3351 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3352 tag_with_dot_errors))
3353
dgn4401aa52015-04-29 16:26:173354 return results
3355
3356
Yoland Yanb92fa522017-08-28 17:37:063357def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3358 """Checks that junit.framework.* is no longer used."""
3359 deprecated_junit_framework_pattern = input_api.re.compile(
3360 r'^import junit\.framework\..*;',
3361 input_api.re.MULTILINE)
3362 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493363 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063364 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133365 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063366 for line_num, line in f.ChangedContents():
3367 if deprecated_junit_framework_pattern.search(line):
3368 errors.append("%s:%d" % (f.LocalPath(), line_num))
3369
3370 results = []
3371 if errors:
3372 results.append(output_api.PresubmitError(
3373 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3374 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3375 ' if you have any question.', errors))
3376 return results
3377
3378
3379def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3380 """Checks that if new Java test classes have inheritance.
3381 Either the new test class is JUnit3 test or it is a JUnit4 test class
3382 with a base class, either case is undesirable.
3383 """
3384 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3385
3386 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493387 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063388 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133389 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063390 if not f.OldContents():
3391 class_declaration_start_flag = False
3392 for line_num, line in f.ChangedContents():
3393 if class_declaration_pattern.search(line):
3394 class_declaration_start_flag = True
3395 if class_declaration_start_flag and ' extends ' in line:
3396 errors.append('%s:%d' % (f.LocalPath(), line_num))
3397 if '{' in line:
3398 class_declaration_start_flag = False
3399
3400 results = []
3401 if errors:
3402 results.append(output_api.PresubmitPromptWarning(
3403 'The newly created files include Test classes that inherits from base'
3404 ' class. Please do not use inheritance in JUnit4 tests or add new'
3405 ' JUnit3 tests. Contact [email protected] if you have any'
3406 ' questions.', errors))
3407 return results
3408
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203409
yolandyan45001472016-12-21 21:12:423410def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3411 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3412 deprecated_annotation_import_pattern = input_api.re.compile(
3413 r'^import android\.test\.suitebuilder\.annotation\..*;',
3414 input_api.re.MULTILINE)
3415 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493416 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423417 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133418 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423419 for line_num, line in f.ChangedContents():
3420 if deprecated_annotation_import_pattern.search(line):
3421 errors.append("%s:%d" % (f.LocalPath(), line_num))
3422
3423 results = []
3424 if errors:
3425 results.append(output_api.PresubmitError(
3426 'Annotations in android.test.suitebuilder.annotation have been'
3427 ' deprecated since API level 24. Please use android.support.test.filters'
3428 ' from //third_party/android_support_test_runner:runner_java instead.'
3429 ' Contact [email protected] if you have any questions.', errors))
3430 return results
3431
3432
agrieve7b6479d82015-10-07 14:24:223433def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3434 """Checks if MDPI assets are placed in a correct directory."""
3435 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3436 ('/res/drawable/' in f.LocalPath() or
3437 '/res/drawable-ldrtl/' in f.LocalPath()))
3438 errors = []
3439 for f in input_api.AffectedFiles(include_deletes=False,
3440 file_filter=file_filter):
3441 errors.append(' %s' % f.LocalPath())
3442
3443 results = []
3444 if errors:
3445 results.append(output_api.PresubmitError(
3446 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3447 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3448 '/res/drawable-ldrtl/.\n'
3449 'Contact [email protected] if you have questions.', errors))
3450 return results
3451
3452
Nate Fischer535972b2017-09-16 01:06:183453def _CheckAndroidWebkitImports(input_api, output_api):
3454 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353455 android.webview.ValueCallback except in the WebView glue layer
3456 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183457 """
3458 valuecallback_import_pattern = input_api.re.compile(
3459 r'^import android\.webkit\.ValueCallback;$')
3460
3461 errors = []
3462
3463 sources = lambda affected_file: input_api.FilterSourceFile(
3464 affected_file,
3465 black_list=(_EXCLUDED_PATHS +
3466 _TEST_CODE_EXCLUDED_PATHS +
3467 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353468 (r'^android_webview[\\/]glue[\\/].*',
3469 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493470 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183471
3472 for f in input_api.AffectedSourceFiles(sources):
3473 for line_num, line in f.ChangedContents():
3474 if valuecallback_import_pattern.search(line):
3475 errors.append("%s:%d" % (f.LocalPath(), line_num))
3476
3477 results = []
3478
3479 if errors:
3480 results.append(output_api.PresubmitError(
3481 'android.webkit.ValueCallback usage is detected outside of the glue'
3482 ' layer. To stay compatible with the support library, android.webkit.*'
3483 ' classes should only be used inside the glue layer and'
3484 ' org.chromium.base.Callback should be used instead.',
3485 errors))
3486
3487 return results
3488
3489
Becky Zhou7c69b50992018-12-10 19:37:573490def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3491 """Checks Android XML styles """
3492 import sys
3493 original_sys_path = sys.path
3494 try:
3495 sys.path = sys.path + [input_api.os_path.join(
3496 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3497 import checkxmlstyle
3498 finally:
3499 # Restore sys.path to what it was before.
3500 sys.path = original_sys_path
3501
3502 if is_check_on_upload:
3503 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3504 else:
3505 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3506
3507
agrievef32bcc72016-04-04 14:57:403508class PydepsChecker(object):
3509 def __init__(self, input_api, pydeps_files):
3510 self._file_cache = {}
3511 self._input_api = input_api
3512 self._pydeps_files = pydeps_files
3513
3514 def _LoadFile(self, path):
3515 """Returns the list of paths within a .pydeps file relative to //."""
3516 if path not in self._file_cache:
3517 with open(path) as f:
3518 self._file_cache[path] = f.read()
3519 return self._file_cache[path]
3520
3521 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3522 """Returns an interable of paths within the .pydep, relativized to //."""
3523 os_path = self._input_api.os_path
3524 pydeps_dir = os_path.dirname(pydeps_path)
3525 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3526 if not l.startswith('*'))
3527 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3528
3529 def _CreateFilesToPydepsMap(self):
3530 """Returns a map of local_path -> list_of_pydeps."""
3531 ret = {}
3532 for pydep_local_path in self._pydeps_files:
3533 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3534 ret.setdefault(path, []).append(pydep_local_path)
3535 return ret
3536
3537 def ComputeAffectedPydeps(self):
3538 """Returns an iterable of .pydeps files that might need regenerating."""
3539 affected_pydeps = set()
3540 file_to_pydeps_map = None
3541 for f in self._input_api.AffectedFiles(include_deletes=True):
3542 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463543 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3544 # subrepositories. We can't figure out which files change, so re-check
3545 # all files.
3546 # Changes to print_python_deps.py affect all .pydeps.
3547 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403548 return self._pydeps_files
3549 elif local_path.endswith('.pydeps'):
3550 if local_path in self._pydeps_files:
3551 affected_pydeps.add(local_path)
3552 elif local_path.endswith('.py'):
3553 if file_to_pydeps_map is None:
3554 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3555 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3556 return affected_pydeps
3557
3558 def DetermineIfStale(self, pydeps_path):
3559 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413560 import difflib
John Budorick47ca3fe2018-02-10 00:53:103561 import os
3562
agrievef32bcc72016-04-04 14:57:403563 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3564 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103565 env = dict(os.environ)
3566 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403567 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103568 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413569 old_contents = old_pydeps_data[2:]
3570 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403571 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413572 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403573
3574
Tibor Goldschwendt360793f72019-06-25 18:23:493575def _ParseGclientArgs():
3576 args = {}
3577 with open('build/config/gclient_args.gni', 'r') as f:
3578 for line in f:
3579 line = line.strip()
3580 if not line or line.startswith('#'):
3581 continue
3582 attribute, value = line.split('=')
3583 args[attribute.strip()] = value.strip()
3584 return args
3585
3586
agrievef32bcc72016-04-04 14:57:403587def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3588 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403589 # This check is for Python dependency lists (.pydeps files), and involves
3590 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3591 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283592 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003593 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493594 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403595 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3596 results = []
3597 # First, check for new / deleted .pydeps.
3598 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033599 # Check whether we are running the presubmit check for a file in src.
3600 # f.LocalPath is relative to repo (src, or internal repo).
3601 # os_path.exists is relative to src repo.
3602 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3603 # to src and we can conclude that the pydeps is in src.
3604 if input_api.os_path.exists(f.LocalPath()):
3605 if f.LocalPath().endswith('.pydeps'):
3606 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3607 results.append(output_api.PresubmitError(
3608 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3609 'remove %s' % f.LocalPath()))
3610 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3611 results.append(output_api.PresubmitError(
3612 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3613 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403614
3615 if results:
3616 return results
3617
3618 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3619
3620 for pydep_path in checker.ComputeAffectedPydeps():
3621 try:
phajdan.jr0d9878552016-11-04 10:49:413622 result = checker.DetermineIfStale(pydep_path)
3623 if result:
3624 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403625 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413626 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3627 'To regenerate, run:\n\n %s' %
3628 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403629 except input_api.subprocess.CalledProcessError as error:
3630 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3631 long_text=error.output)]
3632
3633 return results
3634
3635
glidere61efad2015-02-18 17:39:433636def _CheckSingletonInHeaders(input_api, output_api):
3637 """Checks to make sure no header files have |Singleton<|."""
3638 def FileFilter(affected_file):
3639 # It's ok for base/memory/singleton.h to have |Singleton<|.
3640 black_list = (_EXCLUDED_PATHS +
3641 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043642 (r"^base[\\/]memory[\\/]singleton\.h$",
3643 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473644 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433645 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3646
sergeyu34d21222015-09-16 00:11:443647 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433648 files = []
3649 for f in input_api.AffectedSourceFiles(FileFilter):
3650 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3651 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3652 contents = input_api.ReadFile(f)
3653 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243654 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433655 pattern.search(line)):
3656 files.append(f)
3657 break
3658
3659 if files:
yolandyandaabc6d2016-04-18 18:29:393660 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443661 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433662 'Please move them to an appropriate source file so that the ' +
3663 'template gets instantiated in a single compilation unit.',
3664 files) ]
3665 return []
3666
3667
[email protected]fd20b902014-05-09 02:14:533668_DEPRECATED_CSS = [
3669 # Values
3670 ( "-webkit-box", "flex" ),
3671 ( "-webkit-inline-box", "inline-flex" ),
3672 ( "-webkit-flex", "flex" ),
3673 ( "-webkit-inline-flex", "inline-flex" ),
3674 ( "-webkit-min-content", "min-content" ),
3675 ( "-webkit-max-content", "max-content" ),
3676
3677 # Properties
3678 ( "-webkit-background-clip", "background-clip" ),
3679 ( "-webkit-background-origin", "background-origin" ),
3680 ( "-webkit-background-size", "background-size" ),
3681 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443682 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533683
3684 # Functions
3685 ( "-webkit-gradient", "gradient" ),
3686 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3687 ( "-webkit-linear-gradient", "linear-gradient" ),
3688 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3689 ( "-webkit-radial-gradient", "radial-gradient" ),
3690 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3691]
3692
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203693
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493694# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243695def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533696 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253697 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343698 documentation and iOS CSS for dom distiller
3699 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253700 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533701 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493702 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253703 black_list = (_EXCLUDED_PATHS +
3704 _TEST_CODE_EXCLUDED_PATHS +
3705 input_api.DEFAULT_BLACK_LIST +
3706 (r"^chrome/common/extensions/docs",
3707 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343708 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443709 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253710 r"^native_client_sdk"))
3711 file_filter = lambda f: input_api.FilterSourceFile(
3712 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533713 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3714 for line_num, line in fpath.ChangedContents():
3715 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023716 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533717 results.append(output_api.PresubmitError(
3718 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3719 (fpath.LocalPath(), line_num, deprecated_value, value)))
3720 return results
3721
mohan.reddyf21db962014-10-16 12:26:473722
rlanday6802cf632017-05-30 17:48:363723def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363724 bad_files = {}
3725 for f in input_api.AffectedFiles(include_deletes=False):
3726 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493727 not f.LocalPath().startswith('third_party/blink') and
3728 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363729 continue
3730
Daniel Bratell65b033262019-04-23 08:17:063731 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363732 continue
3733
Vaclav Brozekd5de76a2018-03-17 07:57:503734 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363735 if "#include" in line and "../" in line]
3736 if not relative_includes:
3737 continue
3738 bad_files[f.LocalPath()] = relative_includes
3739
3740 if not bad_files:
3741 return []
3742
3743 error_descriptions = []
3744 for file_path, bad_lines in bad_files.iteritems():
3745 error_description = file_path
3746 for line in bad_lines:
3747 error_description += '\n ' + line
3748 error_descriptions.append(error_description)
3749
3750 results = []
3751 results.append(output_api.PresubmitError(
3752 'You added one or more relative #include paths (including "../").\n'
3753 'These shouldn\'t be used because they can be used to include headers\n'
3754 'from code that\'s not correctly specified as a dependency in the\n'
3755 'relevant BUILD.gn file(s).',
3756 error_descriptions))
3757
3758 return results
3759
Takeshi Yoshinoe387aa32017-08-02 13:16:133760
Daniel Bratell65b033262019-04-23 08:17:063761def _CheckForCcIncludes(input_api, output_api):
3762 """Check that nobody tries to include a cc file. It's a relatively
3763 common error which results in duplicate symbols in object
3764 files. This may not always break the build until someone later gets
3765 very confusing linking errors."""
3766 results = []
3767 for f in input_api.AffectedFiles(include_deletes=False):
3768 # We let third_party code do whatever it wants
3769 if (f.LocalPath().startswith('third_party') and
3770 not f.LocalPath().startswith('third_party/blink') and
3771 not f.LocalPath().startswith('third_party\\blink')):
3772 continue
3773
3774 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3775 continue
3776
3777 for _, line in f.ChangedContents():
3778 if line.startswith('#include "'):
3779 included_file = line.split('"')[1]
3780 if _IsCPlusPlusFile(input_api, included_file):
3781 # The most common naming for external files with C++ code,
3782 # apart from standard headers, is to call them foo.inc, but
3783 # Chromium sometimes uses foo-inc.cc so allow that as well.
3784 if not included_file.endswith(('.h', '-inc.cc')):
3785 results.append(output_api.PresubmitError(
3786 'Only header files or .inc files should be included in other\n'
3787 'C++ files. Compiling the contents of a cc file more than once\n'
3788 'will cause duplicate information in the build which may later\n'
3789 'result in strange link_errors.\n' +
3790 f.LocalPath() + ':\n ' +
3791 line))
3792
3793 return results
3794
3795
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203796def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3797 if not isinstance(key, ast.Str):
3798 return 'Key at line %d must be a string literal' % key.lineno
3799 if not isinstance(value, ast.Dict):
3800 return 'Value at line %d must be a dict' % value.lineno
3801 if len(value.keys) != 1:
3802 return 'Dict at line %d must have single entry' % value.lineno
3803 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3804 return (
3805 'Entry at line %d must have a string literal \'filepath\' as key' %
3806 value.lineno)
3807 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133808
Takeshi Yoshinoe387aa32017-08-02 13:16:133809
Sergey Ulanov4af16052018-11-08 02:41:463810def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203811 if not isinstance(key, ast.Str):
3812 return 'Key at line %d must be a string literal' % key.lineno
3813 if not isinstance(value, ast.List):
3814 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463815 for element in value.elts:
3816 if not isinstance(element, ast.Str):
3817 return 'Watchlist elements on line %d is not a string' % key.lineno
3818 if not email_regex.match(element.s):
3819 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3820 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203821 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133822
Takeshi Yoshinoe387aa32017-08-02 13:16:133823
Sergey Ulanov4af16052018-11-08 02:41:463824def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203825 mismatch_template = (
3826 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3827 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133828
Sergey Ulanov4af16052018-11-08 02:41:463829 email_regex = input_api.re.compile(
3830 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3831
3832 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203833 i = 0
3834 last_key = ''
3835 while True:
3836 if i >= len(wd_dict.keys):
3837 if i >= len(w_dict.keys):
3838 return None
3839 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3840 elif i >= len(w_dict.keys):
3841 return (
3842 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133843
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203844 wd_key = wd_dict.keys[i]
3845 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133846
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203847 result = _CheckWatchlistDefinitionsEntrySyntax(
3848 wd_key, wd_dict.values[i], ast)
3849 if result is not None:
3850 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133851
Sergey Ulanov4af16052018-11-08 02:41:463852 result = _CheckWatchlistsEntrySyntax(
3853 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203854 if result is not None:
3855 return 'Bad entry in WATCHLISTS dict: %s' % result
3856
3857 if wd_key.s != w_key.s:
3858 return mismatch_template % (
3859 '%s at line %d' % (wd_key.s, wd_key.lineno),
3860 '%s at line %d' % (w_key.s, w_key.lineno))
3861
3862 if wd_key.s < last_key:
3863 return (
3864 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3865 (wd_key.lineno, w_key.lineno))
3866 last_key = wd_key.s
3867
3868 i = i + 1
3869
3870
Sergey Ulanov4af16052018-11-08 02:41:463871def _CheckWATCHLISTSSyntax(expression, input_api):
3872 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203873 if not isinstance(expression, ast.Expression):
3874 return 'WATCHLISTS file must contain a valid expression'
3875 dictionary = expression.body
3876 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3877 return 'WATCHLISTS file must have single dict with exactly two entries'
3878
3879 first_key = dictionary.keys[0]
3880 first_value = dictionary.values[0]
3881 second_key = dictionary.keys[1]
3882 second_value = dictionary.values[1]
3883
3884 if (not isinstance(first_key, ast.Str) or
3885 first_key.s != 'WATCHLIST_DEFINITIONS' or
3886 not isinstance(first_value, ast.Dict)):
3887 return (
3888 'The first entry of the dict in WATCHLISTS file must be '
3889 'WATCHLIST_DEFINITIONS dict')
3890
3891 if (not isinstance(second_key, ast.Str) or
3892 second_key.s != 'WATCHLISTS' or
3893 not isinstance(second_value, ast.Dict)):
3894 return (
3895 'The second entry of the dict in WATCHLISTS file must be '
3896 'WATCHLISTS dict')
3897
Sergey Ulanov4af16052018-11-08 02:41:463898 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133899
3900
3901def _CheckWATCHLISTS(input_api, output_api):
3902 for f in input_api.AffectedFiles(include_deletes=False):
3903 if f.LocalPath() == 'WATCHLISTS':
3904 contents = input_api.ReadFile(f, 'r')
3905
3906 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203907 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133908 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203909 # Get an AST tree for it and scan the tree for detailed style checking.
3910 expression = input_api.ast.parse(
3911 contents, filename='WATCHLISTS', mode='eval')
3912 except ValueError as e:
3913 return [output_api.PresubmitError(
3914 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3915 except SyntaxError as e:
3916 return [output_api.PresubmitError(
3917 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3918 except TypeError as e:
3919 return [output_api.PresubmitError(
3920 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133921
Sergey Ulanov4af16052018-11-08 02:41:463922 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203923 if result is not None:
3924 return [output_api.PresubmitError(result)]
3925 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133926
3927 return []
3928
3929
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193930def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3931 """Checks that newly added header files have corresponding GN changes.
3932 Note that this is only a heuristic. To be precise, run script:
3933 build/check_gn_headers.py.
3934 """
3935
3936 def headers(f):
3937 return input_api.FilterSourceFile(
3938 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3939
3940 new_headers = []
3941 for f in input_api.AffectedSourceFiles(headers):
3942 if f.Action() != 'A':
3943 continue
3944 new_headers.append(f.LocalPath())
3945
3946 def gn_files(f):
3947 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3948
3949 all_gn_changed_contents = ''
3950 for f in input_api.AffectedSourceFiles(gn_files):
3951 for _, line in f.ChangedContents():
3952 all_gn_changed_contents += line
3953
3954 problems = []
3955 for header in new_headers:
3956 basename = input_api.os_path.basename(header)
3957 if basename not in all_gn_changed_contents:
3958 problems.append(header)
3959
3960 if problems:
3961 return [output_api.PresubmitPromptWarning(
3962 'Missing GN changes for new header files', items=sorted(problems),
3963 long_text='Please double check whether newly added header files need '
3964 'corresponding changes in gn or gni files.\nThis checking is only a '
3965 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3966 'Read https://crbug.com/661774 for more info.')]
3967 return []
3968
3969
Michael Giuffridad3bc8672018-10-25 22:48:023970def _CheckCorrectProductNameInMessages(input_api, output_api):
3971 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3972
3973 This assumes we won't intentionally reference one product from the other
3974 product.
3975 """
3976 all_problems = []
3977 test_cases = [{
3978 "filename_postfix": "google_chrome_strings.grd",
3979 "correct_name": "Chrome",
3980 "incorrect_name": "Chromium",
3981 }, {
3982 "filename_postfix": "chromium_strings.grd",
3983 "correct_name": "Chromium",
3984 "incorrect_name": "Chrome",
3985 }]
3986
3987 for test_case in test_cases:
3988 problems = []
3989 filename_filter = lambda x: x.LocalPath().endswith(
3990 test_case["filename_postfix"])
3991
3992 # Check each new line. Can yield false positives in multiline comments, but
3993 # easier than trying to parse the XML because messages can have nested
3994 # children, and associating message elements with affected lines is hard.
3995 for f in input_api.AffectedSourceFiles(filename_filter):
3996 for line_num, line in f.ChangedContents():
3997 if "<message" in line or "<!--" in line or "-->" in line:
3998 continue
3999 if test_case["incorrect_name"] in line:
4000 problems.append(
4001 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
4002
4003 if problems:
4004 message = (
4005 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
4006 % (test_case["correct_name"], test_case["correct_name"],
4007 test_case["incorrect_name"]))
4008 all_problems.append(
4009 output_api.PresubmitPromptWarning(message, items=problems))
4010
4011 return all_problems
4012
4013
Dirk Pranke3c18a382019-03-15 01:07:514014def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4015 # TODO(crbug.com/941824): We need to make sure the entries in
4016 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4017 # so that users of //buildtools in other projects get the same tooling
4018 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4019 # support to gclient, we can eliminate the duplication and delete
4020 # this presubmit check.
4021
4022 # Update this regexp if new revisions are added to the files.
4023 rev_regexp = input_api.re.compile(
Xiaohui Chen3fdc6742020-02-29 02:13:264024 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:514025
4026 # If a user is changing one revision, they need to change the same
4027 # line in both files. This means that any given change should contain
4028 # exactly the same list of changed lines that match the regexps. The
4029 # replace(' ', '') call allows us to ignore whitespace changes to the
4030 # lines. The 'long_text' parameter to the error will contain the
4031 # list of changed lines in both files, which should make it easy enough
4032 # to spot the error without going overboard in this implementation.
4033 revs_changes = {
4034 'DEPS': {},
4035 'buildtools/DEPS': {},
4036 }
4037 long_text = ''
4038
4039 for f in input_api.AffectedFiles(
4040 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4041 for line_num, line in f.ChangedContents():
4042 if rev_regexp.search(line):
4043 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4044 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4045
4046 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4047 return [output_api.PresubmitError(
4048 'Change buildtools revisions in sync in both //DEPS and '
4049 '//buildtools/DEPS.', long_text=long_text + '\n')]
4050 else:
4051 return []
4052
4053
Daniel Bratell93eb6c62019-04-29 20:13:364054def _CheckForTooLargeFiles(input_api, output_api):
4055 """Avoid large files, especially binary files, in the repository since
4056 git doesn't scale well for those. They will be in everyone's repo
4057 clones forever, forever making Chromium slower to clone and work
4058 with."""
4059
4060 # Uploading files to cloud storage is not trivial so we don't want
4061 # to set the limit too low, but the upper limit for "normal" large
4062 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4063 # anything over 20 MB is exceptional.
4064 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4065
4066 too_large_files = []
4067 for f in input_api.AffectedFiles():
4068 # Check both added and modified files (but not deleted files).
4069 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384070 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364071 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4072 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4073
4074 if too_large_files:
4075 message = (
4076 'Do not commit large files to git since git scales badly for those.\n' +
4077 'Instead put the large files in cloud storage and use DEPS to\n' +
4078 'fetch them.\n' + '\n'.join(too_large_files)
4079 )
4080 return [output_api.PresubmitError(
4081 'Too large files found in commit', long_text=message + '\n')]
4082 else:
4083 return []
4084
Max Morozb47503b2019-08-08 21:03:274085
4086def _CheckFuzzTargets(input_api, output_api):
4087 """Checks specific for fuzz target sources."""
4088 EXPORTED_SYMBOLS = [
4089 'LLVMFuzzerInitialize',
4090 'LLVMFuzzerCustomMutator',
4091 'LLVMFuzzerCustomCrossOver',
4092 'LLVMFuzzerMutate',
4093 ]
4094
4095 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4096
4097 def FilterFile(affected_file):
4098 """Ignore libFuzzer source code."""
4099 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4100 black_list = r"^third_party[\\/]libFuzzer"
4101
4102 return input_api.FilterSourceFile(
4103 affected_file,
4104 white_list=[white_list],
4105 black_list=[black_list])
4106
4107 files_with_missing_header = []
4108 for f in input_api.AffectedSourceFiles(FilterFile):
4109 contents = input_api.ReadFile(f, 'r')
4110 if REQUIRED_HEADER in contents:
4111 continue
4112
4113 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4114 files_with_missing_header.append(f.LocalPath())
4115
4116 if not files_with_missing_header:
4117 return []
4118
4119 long_text = (
4120 'If you define any of the libFuzzer optional functions (%s), it is '
4121 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4122 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4123 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4124 'to access command line arguments passed to the fuzzer. Instead, prefer '
4125 'static initialization and shared resources as documented in '
4126 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4127 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4128 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4129 )
4130
4131 return [output_api.PresubmitPromptWarning(
4132 message="Missing '%s' in:" % REQUIRED_HEADER,
4133 items=files_with_missing_header,
4134 long_text=long_text)]
4135
4136
Mohamed Heikald048240a2019-11-12 16:57:374137def _CheckNewImagesWarning(input_api, output_api):
4138 """
4139 Warns authors who add images into the repo to make sure their images are
4140 optimized before committing.
4141 """
4142 images_added = False
4143 image_paths = []
4144 errors = []
4145 filter_lambda = lambda x: input_api.FilterSourceFile(
4146 x,
4147 black_list=(('(?i).*test', r'.*\/junit\/')
4148 + input_api.DEFAULT_BLACK_LIST),
4149 white_list=[r'.*\/(drawable|mipmap)' ]
4150 )
4151 for f in input_api.AffectedFiles(
4152 include_deletes=False, file_filter=filter_lambda):
4153 local_path = f.LocalPath().lower()
4154 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4155 images_added = True
4156 image_paths.append(f)
4157 if images_added:
4158 errors.append(output_api.PresubmitPromptWarning(
4159 'It looks like you are trying to commit some images. If these are '
4160 'non-test-only images, please make sure to read and apply the tips in '
4161 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4162 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4163 'FYI only and will not block your CL on the CQ.', image_paths))
4164 return errors
4165
4166
dgnaa68d5e2015-06-10 10:08:224167def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574168 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224169 results = []
dgnaa68d5e2015-06-10 10:08:224170 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174171 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224172 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294173 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064174 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4175 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424176 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184177 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574178 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374179 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154180 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574181 return results
4182
4183def _AndroidSpecificOnCommitChecks(input_api, output_api):
4184 """Groups commit checks that target android code."""
4185 results = []
4186 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224187 return results
4188
4189
[email protected]22c9bd72011-03-27 16:47:394190def _CommonChecks(input_api, output_api):
4191 """Checks common to both upload and commit."""
4192 results = []
4193 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384194 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544195 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084196
4197 author = input_api.change.author_email
4198 if author and author not in _KNOWN_ROBOTS:
4199 results.extend(
4200 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4201
[email protected]55459852011-08-10 15:17:194202 results.extend(
[email protected]760deea2013-12-10 19:33:494203 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234204 results.extend(
4205 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544206 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184207 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344208 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524209 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224210 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444211 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594212 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314213 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064214 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124215 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184216 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224217 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304218 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494219 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034220 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494221 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444222 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294223 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274224 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074225 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544226 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444227 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394228 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554229 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044230 results.extend(
4231 input_api.canned_checks.CheckChangeHasNoTabs(
4232 input_api,
4233 output_api,
4234 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404235 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164236 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084237 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244238 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474239 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044240 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054241 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144242 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234243 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434244 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404245 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154246 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174247 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264248 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504249 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364250 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064251 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134252 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434253 results.extend(input_api.RunTests(
4254 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144255 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Mustafa Emre Acer51f2f742020-03-09 19:41:124256 results.extend(_CheckTranslationExpectations(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024257 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514258 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364259 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004260 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244261
Vaclav Brozekcdc7defb2018-03-20 09:54:354262 for f in input_api.AffectedFiles():
4263 path, name = input_api.os_path.split(f.LocalPath())
4264 if name == 'PRESUBMIT.py':
4265 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004266 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4267 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074268 # The PRESUBMIT.py file (and the directory containing it) might
4269 # have been affected by being moved or removed, so only try to
4270 # run the tests if they still exist.
4271 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4272 input_api, output_api, full_path,
4273 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394274 return results
[email protected]1f7b4172010-01-28 01:17:344275
[email protected]b337cb5b2011-01-23 21:24:054276
[email protected]b8079ae4a2012-12-05 19:56:494277def _CheckPatchFiles(input_api, output_api):
4278 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4279 if f.LocalPath().endswith(('.orig', '.rej'))]
4280 if problems:
4281 return [output_api.PresubmitError(
4282 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034283 else:
4284 return []
[email protected]b8079ae4a2012-12-05 19:56:494285
4286
Kent Tamura5a8755d2017-06-29 23:37:074287def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214288 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4289 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4290 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074291 include_re = input_api.re.compile(
4292 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4293 extension_re = input_api.re.compile(r'\.[a-z]+$')
4294 errors = []
4295 for f in input_api.AffectedFiles():
4296 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4297 continue
4298 found_line_number = None
4299 found_macro = None
4300 for line_num, line in f.ChangedContents():
4301 match = macro_re.search(line)
4302 if match:
4303 found_line_number = line_num
4304 found_macro = match.group(2)
4305 break
4306 if not found_line_number:
4307 continue
4308
4309 found_include = False
4310 for line in f.NewContents():
4311 if include_re.search(line):
4312 found_include = True
4313 break
4314 if found_include:
4315 continue
4316
4317 if not f.LocalPath().endswith('.h'):
4318 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4319 try:
4320 content = input_api.ReadFile(primary_header_path, 'r')
4321 if include_re.search(content):
4322 continue
4323 except IOError:
4324 pass
4325 errors.append('%s:%d %s macro is used without including build/'
4326 'build_config.h.'
4327 % (f.LocalPath(), found_line_number, found_macro))
4328 if errors:
4329 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4330 return []
4331
4332
[email protected]b00342e7f2013-03-26 16:21:544333def _DidYouMeanOSMacro(bad_macro):
4334 try:
4335 return {'A': 'OS_ANDROID',
4336 'B': 'OS_BSD',
4337 'C': 'OS_CHROMEOS',
4338 'F': 'OS_FREEBSD',
4339 'L': 'OS_LINUX',
4340 'M': 'OS_MACOSX',
4341 'N': 'OS_NACL',
4342 'O': 'OS_OPENBSD',
4343 'P': 'OS_POSIX',
4344 'S': 'OS_SOLARIS',
4345 'W': 'OS_WIN'}[bad_macro[3].upper()]
4346 except KeyError:
4347 return ''
4348
4349
4350def _CheckForInvalidOSMacrosInFile(input_api, f):
4351 """Check for sensible looking, totally invalid OS macros."""
4352 preprocessor_statement = input_api.re.compile(r'^\s*#')
4353 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4354 results = []
4355 for lnum, line in f.ChangedContents():
4356 if preprocessor_statement.search(line):
4357 for match in os_macro.finditer(line):
4358 if not match.group(1) in _VALID_OS_MACROS:
4359 good = _DidYouMeanOSMacro(match.group(1))
4360 did_you_mean = ' (did you mean %s?)' % good if good else ''
4361 results.append(' %s:%d %s%s' % (f.LocalPath(),
4362 lnum,
4363 match.group(1),
4364 did_you_mean))
4365 return results
4366
4367
4368def _CheckForInvalidOSMacros(input_api, output_api):
4369 """Check all affected files for invalid OS macros."""
4370 bad_macros = []
tzik3f295992018-12-04 20:32:234371 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474372 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544373 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4374
4375 if not bad_macros:
4376 return []
4377
4378 return [output_api.PresubmitError(
4379 'Possibly invalid OS macro[s] found. Please fix your code\n'
4380 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4381
lliabraa35bab3932014-10-01 12:16:444382
4383def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4384 """Check all affected files for invalid "if defined" macros."""
4385 ALWAYS_DEFINED_MACROS = (
4386 "TARGET_CPU_PPC",
4387 "TARGET_CPU_PPC64",
4388 "TARGET_CPU_68K",
4389 "TARGET_CPU_X86",
4390 "TARGET_CPU_ARM",
4391 "TARGET_CPU_MIPS",
4392 "TARGET_CPU_SPARC",
4393 "TARGET_CPU_ALPHA",
4394 "TARGET_IPHONE_SIMULATOR",
4395 "TARGET_OS_EMBEDDED",
4396 "TARGET_OS_IPHONE",
4397 "TARGET_OS_MAC",
4398 "TARGET_OS_UNIX",
4399 "TARGET_OS_WIN32",
4400 )
4401 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4402 results = []
4403 for lnum, line in f.ChangedContents():
4404 for match in ifdef_macro.finditer(line):
4405 if match.group(1) in ALWAYS_DEFINED_MACROS:
4406 always_defined = ' %s is always defined. ' % match.group(1)
4407 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4408 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4409 lnum,
4410 always_defined,
4411 did_you_mean))
4412 return results
4413
4414
4415def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4416 """Check all affected files for invalid "if defined" macros."""
4417 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054418 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444419 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054420 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214421 continue
lliabraa35bab3932014-10-01 12:16:444422 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4423 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4424
4425 if not bad_macros:
4426 return []
4427
4428 return [output_api.PresubmitError(
4429 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4430 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4431 bad_macros)]
4432
4433
mlamouria82272622014-09-16 18:45:044434def _CheckForIPCRules(input_api, output_api):
4435 """Check for same IPC rules described in
4436 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4437 """
4438 base_pattern = r'IPC_ENUM_TRAITS\('
4439 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4440 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4441
4442 problems = []
4443 for f in input_api.AffectedSourceFiles(None):
4444 local_path = f.LocalPath()
4445 if not local_path.endswith('.h'):
4446 continue
4447 for line_number, line in f.ChangedContents():
4448 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4449 problems.append(
4450 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4451
4452 if problems:
4453 return [output_api.PresubmitPromptWarning(
4454 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4455 else:
4456 return []
4457
[email protected]b00342e7f2013-03-26 16:21:544458
Stephen Martinis97a394142018-06-07 23:06:054459def _CheckForLongPathnames(input_api, output_api):
4460 """Check to make sure no files being submitted have long paths.
4461 This causes issues on Windows.
4462 """
4463 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194464 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054465 local_path = f.LocalPath()
4466 # Windows has a path limit of 260 characters. Limit path length to 200 so
4467 # that we have some extra for the prefix on dev machines and the bots.
4468 if len(local_path) > 200:
4469 problems.append(local_path)
4470
4471 if problems:
4472 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4473 else:
4474 return []
4475
4476
Daniel Bratell8ba52722018-03-02 16:06:144477def _CheckForIncludeGuards(input_api, output_api):
4478 """Check that header files have proper guards against multiple inclusion.
4479 If a file should not have such guards (and it probably should) then it
4480 should include the string "no-include-guard-because-multiply-included".
4481 """
Daniel Bratell6a75baef62018-06-04 10:04:454482 def is_chromium_header_file(f):
4483 # We only check header files under the control of the Chromium
4484 # project. That is, those outside third_party apart from
4485 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324486 # We also exclude *_message_generator.h headers as they use
4487 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454488 file_with_path = input_api.os_path.normpath(f.LocalPath())
4489 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324490 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454491 (not file_with_path.startswith('third_party') or
4492 file_with_path.startswith(
4493 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144494
4495 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344496 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144497
4498 errors = []
4499
Daniel Bratell6a75baef62018-06-04 10:04:454500 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144501 guard_name = None
4502 guard_line_number = None
4503 seen_guard_end = False
4504
4505 file_with_path = input_api.os_path.normpath(f.LocalPath())
4506 base_file_name = input_api.os_path.splitext(
4507 input_api.os_path.basename(file_with_path))[0]
4508 upper_base_file_name = base_file_name.upper()
4509
4510 expected_guard = replace_special_with_underscore(
4511 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144512
4513 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574514 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4515 # are too many (1000+) files with slight deviations from the
4516 # coding style. The most important part is that the include guard
4517 # is there, and that it's unique, not the name so this check is
4518 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144519 #
4520 # As code becomes more uniform, this could be made stricter.
4521
4522 guard_name_pattern_list = [
4523 # Anything with the right suffix (maybe with an extra _).
4524 r'\w+_H__?',
4525
Daniel Bratell39b5b062018-05-16 18:09:574526 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144527 r'\w+_h',
4528
4529 # Anything including the uppercase name of the file.
4530 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4531 upper_base_file_name)) + r'\w*',
4532 ]
4533 guard_name_pattern = '|'.join(guard_name_pattern_list)
4534 guard_pattern = input_api.re.compile(
4535 r'#ifndef\s+(' + guard_name_pattern + ')')
4536
4537 for line_number, line in enumerate(f.NewContents()):
4538 if 'no-include-guard-because-multiply-included' in line:
4539 guard_name = 'DUMMY' # To not trigger check outside the loop.
4540 break
4541
4542 if guard_name is None:
4543 match = guard_pattern.match(line)
4544 if match:
4545 guard_name = match.group(1)
4546 guard_line_number = line_number
4547
Daniel Bratell39b5b062018-05-16 18:09:574548 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454549 # don't match the chromium style guide, but new files should
4550 # get it right.
4551 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574552 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144553 errors.append(output_api.PresubmitPromptWarning(
4554 'Header using the wrong include guard name %s' % guard_name,
4555 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574556 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144557 else:
4558 # The line after #ifndef should have a #define of the same name.
4559 if line_number == guard_line_number + 1:
4560 expected_line = '#define %s' % guard_name
4561 if line != expected_line:
4562 errors.append(output_api.PresubmitPromptWarning(
4563 'Missing "%s" for include guard' % expected_line,
4564 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4565 'Expected: %r\nGot: %r' % (expected_line, line)))
4566
4567 if not seen_guard_end and line == '#endif // %s' % guard_name:
4568 seen_guard_end = True
4569 elif seen_guard_end:
4570 if line.strip() != '':
4571 errors.append(output_api.PresubmitPromptWarning(
4572 'Include guard %s not covering the whole file' % (
4573 guard_name), [f.LocalPath()]))
4574 break # Nothing else to check and enough to warn once.
4575
4576 if guard_name is None:
4577 errors.append(output_api.PresubmitPromptWarning(
4578 'Missing include guard %s' % expected_guard,
4579 [f.LocalPath()],
4580 'Missing include guard in %s\n'
4581 'Recommended name: %s\n'
4582 'This check can be disabled by having the string\n'
4583 'no-include-guard-because-multiply-included in the header.' %
4584 (f.LocalPath(), expected_guard)))
4585
4586 return errors
4587
4588
mostynbb639aca52015-01-07 20:31:234589def _CheckForWindowsLineEndings(input_api, output_api):
4590 """Check source code and known ascii text files for Windows style line
4591 endings.
4592 """
earthdok1b5e0ee2015-03-10 15:19:104593 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234594
4595 file_inclusion_pattern = (
4596 known_text_files,
4597 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4598 )
4599
mostynbb639aca52015-01-07 20:31:234600 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534601 source_file_filter = lambda f: input_api.FilterSourceFile(
4602 f, white_list=file_inclusion_pattern, black_list=None)
4603 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504604 include_file = False
4605 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234606 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504607 include_file = True
4608 if include_file:
4609 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234610
4611 if problems:
4612 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4613 'these files to contain Windows style line endings?\n' +
4614 '\n'.join(problems))]
4615
4616 return []
4617
4618
Vaclav Brozekd5de76a2018-03-17 07:57:504619def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134620 """Checks that all source files use SYSLOG properly."""
4621 syslog_files = []
4622 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564623 for line_number, line in f.ChangedContents():
4624 if 'SYSLOG' in line:
4625 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4626
pastarmovj89f7ee12016-09-20 14:58:134627 if syslog_files:
4628 return [output_api.PresubmitPromptWarning(
4629 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4630 ' calls.\nFiles to check:\n', items=syslog_files)]
4631 return []
4632
4633
[email protected]1f7b4172010-01-28 01:17:344634def CheckChangeOnUpload(input_api, output_api):
4635 results = []
4636 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474637 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284638 results.extend(
jam93a6ee792017-02-08 23:59:224639 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194640 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224641 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134642 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164643 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534644 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194645 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274646 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544647 return results
[email protected]ca8d1982009-02-19 16:33:124648
4649
[email protected]1bfb8322014-04-23 01:02:414650def GetTryServerMasterForBot(bot):
4651 """Returns the Try Server master for the given bot.
4652
[email protected]0bb112362014-07-26 04:38:324653 It tries to guess the master from the bot name, but may still fail
4654 and return None. There is no longer a default master.
4655 """
4656 # Potentially ambiguous bot names are listed explicitly.
4657 master_map = {
tandriie5587792016-07-14 00:34:504658 'chromium_presubmit': 'master.tryserver.chromium.linux',
4659 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414660 }
[email protected]0bb112362014-07-26 04:38:324661 master = master_map.get(bot)
4662 if not master:
wnwen4fbaab82016-05-25 12:54:364663 if 'android' in bot:
tandriie5587792016-07-14 00:34:504664 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364665 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504666 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324667 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504668 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324669 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504670 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324671 return master
[email protected]1bfb8322014-04-23 01:02:414672
4673
[email protected]ca8d1982009-02-19 16:33:124674def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544675 results = []
[email protected]1f7b4172010-01-28 01:17:344676 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574677 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544678 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274679 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344680 input_api,
4681 output_api,
[email protected]2fdd1f362013-01-16 03:56:034682 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274683
jam93a6ee792017-02-08 23:59:224684 results.extend(
4685 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544686 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4687 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384688 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4689 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414690 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4691 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544692 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144693
4694
4695def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144696 import os
4697 import sys
4698 from io import StringIO
4699
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144700 new_or_added_paths = set(f.LocalPath()
4701 for f in input_api.AffectedFiles()
4702 if (f.Action() == 'A' or f.Action() == 'M'))
4703 removed_paths = set(f.LocalPath()
4704 for f in input_api.AffectedFiles(include_deletes=True)
4705 if f.Action() == 'D')
4706
4707 affected_grds = [f for f in input_api.AffectedFiles()
4708 if (f.LocalPath().endswith('.grd') or
4709 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164710 if not affected_grds:
4711 return []
4712
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144713 affected_png_paths = [f.AbsoluteLocalPath()
4714 for f in input_api.AffectedFiles()
4715 if (f.LocalPath().endswith('.png'))]
4716
4717 # Check for screenshots. Developers can upload screenshots using
4718 # tools/translation/upload_screenshots.py which finds and uploads
4719 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4720 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4721 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4722 #
4723 # The logic here is as follows:
4724 #
4725 # - If the CL has a .png file under the screenshots directory for a grd
4726 # file, warn the developer. Actual images should never be checked into the
4727 # Chrome repo.
4728 #
4729 # - If the CL contains modified or new messages in grd files and doesn't
4730 # contain the corresponding .sha1 files, warn the developer to add images
4731 # and upload them via tools/translation/upload_screenshots.py.
4732 #
4733 # - If the CL contains modified or new messages in grd files and the
4734 # corresponding .sha1 files, everything looks good.
4735 #
4736 # - If the CL contains removed messages in grd files but the corresponding
4737 # .sha1 files aren't removed, warn the developer to remove them.
4738 unnecessary_screenshots = []
4739 missing_sha1 = []
4740 unnecessary_sha1_files = []
4741
4742
4743 def _CheckScreenshotAdded(screenshots_dir, message_id):
4744 sha1_path = input_api.os_path.join(
4745 screenshots_dir, message_id + '.png.sha1')
4746 if sha1_path not in new_or_added_paths:
4747 missing_sha1.append(sha1_path)
4748
4749
4750 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4751 sha1_path = input_api.os_path.join(
4752 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034753 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144754 unnecessary_sha1_files.append(sha1_path)
4755
meacer8c0d3832019-12-26 21:46:164756 try:
4757 old_sys_path = sys.path
4758 sys.path = sys.path + [input_api.os_path.join(
4759 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4760 from helper import grd_helper
4761 finally:
4762 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144763
4764 for f in affected_grds:
4765 file_path = f.LocalPath()
4766 old_id_to_msg_map = {}
4767 new_id_to_msg_map = {}
Mustafa Emre Acerd697ac92020-02-06 19:03:384768 # Note that this code doesn't check if the file has been deleted. This is
4769 # OK because it only uses the old and new file contents and doesn't load
4770 # the file via its path.
4771 # It's also possible that a file's content refers to a renamed or deleted
4772 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
4773 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
4774 # .grdp files.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144775 if file_path.endswith('.grdp'):
4776 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584777 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394778 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144779 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584780 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394781 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144782 else:
meacerff8a9b62019-12-10 19:43:584783 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144784 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584785 old_id_to_msg_map = grd_helper.GetGrdMessages(
4786 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144787 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584788 new_id_to_msg_map = grd_helper.GetGrdMessages(
4789 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144790
4791 # Compute added, removed and modified message IDs.
4792 old_ids = set(old_id_to_msg_map)
4793 new_ids = set(new_id_to_msg_map)
4794 added_ids = new_ids - old_ids
4795 removed_ids = old_ids - new_ids
4796 modified_ids = set([])
4797 for key in old_ids.intersection(new_ids):
4798 if (old_id_to_msg_map[key].FormatXml()
4799 != new_id_to_msg_map[key].FormatXml()):
4800 modified_ids.add(key)
4801
4802 grd_name, ext = input_api.os_path.splitext(
4803 input_api.os_path.basename(file_path))
4804 screenshots_dir = input_api.os_path.join(
4805 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4806
4807 # Check the screenshot directory for .png files. Warn if there is any.
4808 for png_path in affected_png_paths:
4809 if png_path.startswith(screenshots_dir):
4810 unnecessary_screenshots.append(png_path)
4811
4812 for added_id in added_ids:
4813 _CheckScreenshotAdded(screenshots_dir, added_id)
4814
4815 for modified_id in modified_ids:
4816 _CheckScreenshotAdded(screenshots_dir, modified_id)
4817
4818 for removed_id in removed_ids:
4819 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4820
4821 results = []
4822 if unnecessary_screenshots:
4823 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394824 'Do not include actual screenshots in the changelist. Run '
4825 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144826 sorted(unnecessary_screenshots)))
4827
4828 if missing_sha1:
4829 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394830 'You are adding or modifying UI strings.\n'
4831 'To ensure the best translations, take screenshots of the relevant UI '
4832 '(https://g.co/chrome/translation) and add these files to your '
4833 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144834
4835 if unnecessary_sha1_files:
4836 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394837 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144838 sorted(unnecessary_sha1_files)))
4839
4840 return results
Mustafa Emre Acer51f2f742020-03-09 19:41:124841
4842
4843def _CheckTranslationExpectations(input_api, output_api,
4844 repo_root=None,
4845 translation_expectations_path=None,
4846 grd_files=None):
4847 import sys
4848 affected_grds = [f for f in input_api.AffectedFiles()
4849 if (f.LocalPath().endswith('.grd') or
4850 f.LocalPath().endswith('.grdp'))]
4851 if not affected_grds:
4852 return []
4853
4854 try:
4855 old_sys_path = sys.path
4856 sys.path = sys.path + [
4857 input_api.os_path.join(
4858 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4859 from helper import git_helper
4860 from helper import translation_helper
4861 finally:
4862 sys.path = old_sys_path
4863
4864 # Check that translation expectations can be parsed and we can get a list of
4865 # translatable grd files. |repo_root| and |translation_expectations_path| are
4866 # only passed by tests.
4867 if not repo_root:
4868 repo_root = input_api.PresubmitLocalPath()
4869 if not translation_expectations_path:
4870 translation_expectations_path = input_api.os_path.join(
4871 repo_root, 'tools', 'gritsettings',
4872 'translation_expectations.pyl')
4873 if not grd_files:
4874 grd_files = git_helper.list_grds_in_repository(repo_root)
4875
4876 try:
4877 translation_helper.get_translatable_grds(repo_root, grd_files,
4878 translation_expectations_path)
4879 except Exception as e:
4880 return [output_api.PresubmitNotifyResult(
4881 'Failed to get a list of translatable grd files. This happens when:\n'
4882 ' - One of the modified grd or grdp files cannot be parsed or\n'
4883 ' - %s is not updated.\n'
4884 'Stack:\n%s' % (translation_expectations_path, str(e)))]
4885 return []