blob: 56ed1c4c771c88ce417acce8f999333b8d1f2cee [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0413 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py",
14 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py",
15 r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
16 r"^net[\\/]tools[\\/]spdyshark[\\/].*",
17 r"^skia[\\/].*",
Kent Tamura32dbbcb2018-11-30 12:28:4918 r"^third_party[\\/]blink[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0419 r"^third_party[\\/]breakpad[\\/].*",
Darwin Huangd74a9d32019-07-17 17:58:4620 # sqlite is an imported third party dependency.
21 r"^third_party[\\/]sqlite[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0422 r"^v8[\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5324 r".+_autogen\.h$",
John Budorick1e701d322019-09-11 23:35:1225 r".+_pb2\.py$",
Egor Paskoce145c42018-09-28 19:31:0426 r".+[\\/]pnacl_shim\.c$",
27 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
Egor Paskoce145c42018-09-28 19:31:0428 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1429 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0430 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5431 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0432 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4033)
[email protected]ca8d1982009-02-19 16:33:1234
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Fragment of a regular expression that matches C++ and Objective-C++
37# implementation files.
38_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
39
wnwenbdc444e2016-05-25 13:44:1540
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1941# Fragment of a regular expression that matches C++ and Objective-C++
42# header files.
43_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
44
45
[email protected]06e6d0ff2012-12-11 01:36:4446# Regular expression that matches code only used for test binaries
47# (best effort).
48_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0449 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4450 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4451 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1252 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1853 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4454 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0455 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0556 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0457 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4758 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0459 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0860 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0461 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4162 # EarlGrey app side code for tests.
63 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4464)
[email protected]ca8d1982009-02-19 16:33:1265
Daniel Bratell609102be2019-03-27 20:53:2166_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1567
[email protected]eea609a2011-11-18 13:10:1268_TEST_ONLY_WARNING = (
69 'You might be calling functions intended only for testing from\n'
70 'production code. It is OK to ignore this warning if you know what\n'
71 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0772 'not perfect. The commit queue will not block on this warning,\n'
73 'however the android-binary-size trybot will block if the method\n'
74 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1275
76
[email protected]cf9b78f2012-11-14 11:40:2877_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4078 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2179 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
80 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2881
Michael Thiessen44457642020-02-06 00:24:1582# Format: Sequence of tuples containing:
83# * Full import path.
84# * Sequence of strings to show when the pattern matches.
85# * Sequence of path or filename exceptions to this rule
86_BANNED_JAVA_IMPORTS = (
87 (
88 'java.net.URI',
89 (
90 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
91 ),
92 (
93 'net/android/javatests/src/org/chromium/net/'
94 'AndroidProxySelectorTest.java',
95 'components/cronet/',
96 ),
97 ),
98)
wnwenbdc444e2016-05-25 13:44:1599
Daniel Bratell609102be2019-03-27 20:53:21100# Format: Sequence of tuples containing:
101# * String pattern or, if starting with a slash, a regular expression.
102# * Sequence of strings to show when the pattern matches.
103# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:41104_BANNED_JAVA_FUNCTIONS = (
105 (
106 'StrictMode.allowThreadDiskReads()',
107 (
108 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
109 'directly.',
110 ),
111 False,
112 ),
113 (
114 'StrictMode.allowThreadDiskWrites()',
115 (
116 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
117 'directly.',
118 ),
119 False,
120 ),
121)
122
Daniel Bratell609102be2019-03-27 20:53:21123# Format: Sequence of tuples containing:
124# * String pattern or, if starting with a slash, a regular expression.
125# * Sequence of strings to show when the pattern matches.
126# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59127_BANNED_OBJC_FUNCTIONS = (
128 (
129 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59132 'prohibited. Please use CrTrackingArea instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 False,
136 ),
137 (
[email protected]eaae1972014-04-16 04:17:26138 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20139 (
140 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59141 'instead.',
142 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
143 ),
144 False,
145 ),
146 (
147 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20148 (
149 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59150 'Please use |convertPoint:(point) fromView:nil| instead.',
151 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
152 ),
153 True,
154 ),
155 (
156 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59159 'Please use |convertPoint:(point) toView:nil| instead.',
160 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
161 ),
162 True,
163 ),
164 (
165 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59168 'Please use |convertRect:(point) fromView:nil| instead.',
169 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
170 ),
171 True,
172 ),
173 (
174 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20175 (
176 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59177 'Please use |convertRect:(point) toView:nil| instead.',
178 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
179 ),
180 True,
181 ),
182 (
183 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20184 (
185 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59186 'Please use |convertSize:(point) fromView:nil| instead.',
187 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
188 ),
189 True,
190 ),
191 (
192 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20193 (
194 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59195 'Please use |convertSize:(point) toView:nil| instead.',
196 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
197 ),
198 True,
199 ),
jif65398702016-10-27 10:19:48200 (
201 r"/\s+UTF8String\s*]",
202 (
203 'The use of -[NSString UTF8String] is dangerous as it can return null',
204 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
205 'Please use |SysNSStringToUTF8| instead.',
206 ),
207 True,
208 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34209 (
210 r'__unsafe_unretained',
211 (
212 'The use of __unsafe_unretained is almost certainly wrong, unless',
213 'when interacting with NSFastEnumeration or NSInvocation.',
214 'Please use __weak in files build with ARC, nothing otherwise.',
215 ),
216 False,
217 ),
Avi Drissman7382afa02019-04-29 23:27:13218 (
219 'freeWhenDone:NO',
220 (
221 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
222 'Foundation types is prohibited.',
223 ),
224 True,
225 ),
[email protected]127f18ec2012-06-16 05:05:59226)
227
Daniel Bratell609102be2019-03-27 20:53:21228# Format: Sequence of tuples containing:
229# * String pattern or, if starting with a slash, a regular expression.
230# * Sequence of strings to show when the pattern matches.
231# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54232_BANNED_IOS_OBJC_FUNCTIONS = (
233 (
234 r'/\bTEST[(]',
235 (
236 'TEST() macro should not be used in Objective-C++ code as it does not ',
237 'drain the autorelease pool at the end of the test. Use TEST_F() ',
238 'macro instead with a fixture inheriting from PlatformTest (or a ',
239 'typedef).'
240 ),
241 True,
242 ),
243 (
244 r'/\btesting::Test\b',
245 (
246 'testing::Test should not be used in Objective-C++ code as it does ',
247 'not drain the autorelease pool at the end of the test. Use ',
248 'PlatformTest instead.'
249 ),
250 True,
251 ),
252)
253
Peter K. Lee6c03ccff2019-07-15 14:40:05254# Format: Sequence of tuples containing:
255# * String pattern or, if starting with a slash, a regular expression.
256# * Sequence of strings to show when the pattern matches.
257# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
258_BANNED_IOS_EGTEST_FUNCTIONS = (
259 (
260 r'/\bEXPECT_OCMOCK_VERIFY\b',
261 (
262 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
263 'it is meant for GTests. Use [mock verify] instead.'
264 ),
265 True,
266 ),
267)
268
danakj7a2b7082019-05-21 21:13:51269# Directories that contain deprecated Bind() or Callback types.
270# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36271# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51272# echo "-- $i"
danakj710b4c02019-11-28 16:08:45273# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51274# done
275#
276# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
277# when they have been converted to modern callback types (OnceCallback,
278# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
279# checks for them and prevent regressions.
280_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
danakj7a2b7082019-05-21 21:13:51281 '^apps/',
danakj7a2b7082019-05-21 21:13:51282 '^base/callback.h', # Intentional.
283 '^chrome/app/',
284 '^chrome/browser/',
285 '^chrome/chrome_elf/',
danakj7a2b7082019-05-21 21:13:51286 '^chrome/common/',
287 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51288 '^chrome/renderer/',
289 '^chrome/services/',
290 '^chrome/test/',
291 '^chrome/tools/',
292 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51293 '^chromecast/media/',
294 '^chromecast/metrics/',
295 '^chromecast/net/',
296 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51297 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51298 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51299 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51300 '^components/arc/',
301 '^components/assist_ranker/',
302 '^components/autofill/',
303 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51304 '^components/browser_watcher/',
danakj7a2b7082019-05-21 21:13:51305 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51306 '^components/chromeos_camera/',
307 '^components/component_updater/',
308 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51309 '^components/cronet/',
310 '^components/data_reduction_proxy/',
danakj7a2b7082019-05-21 21:13:51311 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36312 '^components/dom_distiller/',
danakj7a2b7082019-05-21 21:13:51313 '^components/download/',
314 '^components/drive/',
315 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51316 '^components/feature_engagement/',
317 '^components/feedback/',
318 '^components/flags_ui/',
319 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51320 '^components/guest_view/',
321 '^components/heap_profiling/',
322 '^components/history/',
323 '^components/image_fetcher/',
324 '^components/invalidation/',
325 '^components/keyed_service/',
326 '^components/login/',
327 '^components/metrics/',
328 '^components/metrics_services_manager/',
329 '^components/nacl/',
330 '^components/navigation_interception/',
331 '^components/net_log/',
332 '^components/network_time/',
333 '^components/ntp_snippets/',
334 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51335 '^components/offline_pages/',
336 '^components/omnibox/',
337 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51338 '^components/password_manager/',
339 '^components/payments/',
340 '^components/plugins/',
341 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51342 '^components/proxy_config/',
343 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51344 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51345 '^components/rlz/',
346 '^components/safe_browsing/',
347 '^components/search_engines/',
348 '^components/search_provider_logos/',
349 '^components/security_interstitials/',
350 '^components/security_state/',
351 '^components/services/',
352 '^components/sessions/',
353 '^components/signin/',
354 '^components/ssl_errors/',
355 '^components/storage_monitor/',
356 '^components/subresource_filter/',
357 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51358 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51359 '^components/sync_preferences/',
360 '^components/sync_sessions/',
361 '^components/test/',
362 '^components/tracing/',
363 '^components/translate/',
364 '^components/ukm/',
365 '^components/update_client/',
366 '^components/upload_list/',
367 '^components/variations/',
368 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51369 '^components/webcrypto/',
370 '^components/webdata/',
371 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51372 '^device/bluetooth/',
Alan Cutter04a00642020-03-02 01:45:20373 '^extensions/browser/',
374 '^extensions/renderer/',
Alan Cutter04a00642020-03-02 01:45:20375 '^extensions/test/',
danakj7a2b7082019-05-21 21:13:51376 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51377 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51378 '^ios/chrome/',
379 '^ios/components/',
380 '^ios/net/',
381 '^ios/web/',
382 '^ios/web_view/',
383 '^ipc/',
384 '^media/audio/',
385 '^media/base/',
danakjc8576092019-11-26 19:01:36386 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51387 '^media/capture/',
388 '^media/cast/',
389 '^media/cdm/',
390 '^media/device_monitors/',
391 '^media/ffmpeg/',
392 '^media/filters/',
393 '^media/formats/',
394 '^media/gpu/',
395 '^media/mojo/',
396 '^media/muxers/',
397 '^media/remoting/',
398 '^media/renderers/',
399 '^media/test/',
danakj7a2b7082019-05-21 21:13:51400 '^net/',
401 '^ppapi/proxy/',
402 '^ppapi/shared_impl/',
403 '^ppapi/tests/',
404 '^ppapi/thunk/',
405 '^remoting/base/',
406 '^remoting/client/',
danakj7a2b7082019-05-21 21:13:51407 '^remoting/host/',
408 '^remoting/internal/',
danakj7a2b7082019-05-21 21:13:51409 '^remoting/protocol/',
danakj7a2b7082019-05-21 21:13:51410 '^services/',
danakj7a2b7082019-05-21 21:13:51411 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51412 '^tools/clang/base_bind_rewriters/', # Intentional.
413 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51414))
[email protected]127f18ec2012-06-16 05:05:59415
Daniel Bratell609102be2019-03-27 20:53:21416# Format: Sequence of tuples containing:
417# * String pattern or, if starting with a slash, a regular expression.
418# * Sequence of strings to show when the pattern matches.
419# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
420# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59421_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20422 (
Dave Tapuska98199b612019-07-10 13:30:44423 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53424 (
425 'New code should not use NULL. Use nullptr instead.',
426 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20427 False,
thomasandersone7caaa9b2017-03-29 19:22:53428 (),
429 ),
Peter Kasting94a56c42019-10-25 21:54:04430 (
431 r'/\busing namespace ',
432 (
433 'Using directives ("using namespace x") are banned by the Google Style',
434 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
435 'Explicitly qualify symbols or use using declarations ("using x::foo").',
436 ),
437 True,
438 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
439 ),
Antonio Gomes07300d02019-03-13 20:59:57440 # Make sure that gtest's FRIEND_TEST() macro is not used; the
441 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
442 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53443 (
[email protected]23e6cbc2012-06-16 18:51:20444 'FRIEND_TEST(',
445 (
[email protected]e3c945502012-06-26 20:01:49446 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20447 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
448 ),
449 False,
[email protected]7345da02012-11-27 14:31:49450 (),
[email protected]23e6cbc2012-06-16 18:51:20451 ),
452 (
Dave Tapuska98199b612019-07-10 13:30:44453 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53454 (
455 'Chrome clients wishing to select events on X windows should use',
456 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
457 'you are selecting events from the GPU process, or if you are using',
458 'an XDisplay other than gfx::GetXDisplay().',
459 ),
460 True,
461 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40462 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04463 r"^ui[\\/]gl[\\/].*\.cc$",
464 r"^media[\\/]gpu[\\/].*\.cc$",
465 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53466 ),
467 ),
468 (
Dave Tapuska98199b612019-07-10 13:30:44469 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20470 (
thomasanderson11aa41d2017-06-08 22:22:38471 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20472 ),
473 True,
474 (
Egor Paskoce145c42018-09-28 19:31:04475 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
476 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
477 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20478 ),
479 ),
480 (
tomhudsone2c14d552016-05-26 17:07:46481 'setMatrixClip',
482 (
483 'Overriding setMatrixClip() is prohibited; ',
484 'the base function is deprecated. ',
485 ),
486 True,
487 (),
488 ),
489 (
[email protected]52657f62013-05-20 05:30:31490 'SkRefPtr',
491 (
492 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22493 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31494 ),
495 True,
496 (),
497 ),
498 (
499 'SkAutoRef',
500 (
501 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22502 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31503 ),
504 True,
505 (),
506 ),
507 (
508 'SkAutoTUnref',
509 (
510 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22511 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31512 ),
513 True,
514 (),
515 ),
516 (
517 'SkAutoUnref',
518 (
519 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
520 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22521 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31522 ),
523 True,
524 (),
525 ),
[email protected]d89eec82013-12-03 14:10:59526 (
527 r'/HANDLE_EINTR\(.*close',
528 (
529 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
530 'descriptor will be closed, and it is incorrect to retry the close.',
531 'Either call close directly and ignore its return value, or wrap close',
532 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
533 ),
534 True,
535 (),
536 ),
537 (
538 r'/IGNORE_EINTR\((?!.*close)',
539 (
540 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
541 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
542 ),
543 True,
544 (
545 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04546 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
547 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59548 ),
549 ),
[email protected]ec5b3f02014-04-04 18:43:43550 (
551 r'/v8::Extension\(',
552 (
553 'Do not introduce new v8::Extensions into the code base, use',
554 'gin::Wrappable instead. See http://crbug.com/334679',
555 ),
556 True,
[email protected]f55c90ee62014-04-12 00:50:03557 (
Egor Paskoce145c42018-09-28 19:31:04558 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03559 ),
[email protected]ec5b3f02014-04-04 18:43:43560 ),
skyostilf9469f72015-04-20 10:38:52561 (
jame2d1a952016-04-02 00:27:10562 '#pragma comment(lib,',
563 (
564 'Specify libraries to link with in build files and not in the source.',
565 ),
566 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41567 (
tzik3f295992018-12-04 20:32:23568 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04569 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41570 ),
jame2d1a952016-04-02 00:27:10571 ),
fdorayc4ac18d2017-05-01 21:39:59572 (
Gabriel Charette7cc6c432018-04-25 20:52:02573 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59574 (
575 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
576 ),
577 False,
578 (),
579 ),
580 (
Gabriel Charette7cc6c432018-04-25 20:52:02581 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59582 (
583 'Consider using THREAD_CHECKER macros instead of the class directly.',
584 ),
585 False,
586 (),
587 ),
dbeamb6f4fde2017-06-15 04:03:06588 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06589 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
590 (
591 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
592 'deprecated (http://crbug.com/634507). Please avoid converting away',
593 'from the Time types in Chromium code, especially if any math is',
594 'being done on time values. For interfacing with platform/library',
595 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
596 'type converter methods instead. For faking TimeXXX values (for unit',
597 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
598 'other use cases, please contact base/time/OWNERS.',
599 ),
600 False,
601 (),
602 ),
603 (
dbeamb6f4fde2017-06-15 04:03:06604 'CallJavascriptFunctionUnsafe',
605 (
606 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
607 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
608 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
609 ),
610 False,
611 (
Egor Paskoce145c42018-09-28 19:31:04612 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
613 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
614 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06615 ),
616 ),
dskiba1474c2bfd62017-07-20 02:19:24617 (
618 'leveldb::DB::Open',
619 (
620 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
621 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
622 "Chrome's tracing, making their memory usage visible.",
623 ),
624 True,
625 (
626 r'^third_party/leveldatabase/.*\.(cc|h)$',
627 ),
Gabriel Charette0592c3a2017-07-26 12:02:04628 ),
629 (
Chris Mumfordc38afb62017-10-09 17:55:08630 'leveldb::NewMemEnv',
631 (
632 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58633 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
634 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08635 ),
636 True,
637 (
638 r'^third_party/leveldatabase/.*\.(cc|h)$',
639 ),
640 ),
641 (
Gabriel Charetted9839bc2017-07-29 14:17:47642 'RunLoop::QuitCurrent',
643 (
Robert Liao64b7ab22017-08-04 23:03:43644 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
645 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47646 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41647 False,
Gabriel Charetted9839bc2017-07-29 14:17:47648 (),
Gabriel Charettea44975052017-08-21 23:14:04649 ),
650 (
651 'base::ScopedMockTimeMessageLoopTaskRunner',
652 (
Gabriel Charette87cc1af2018-04-25 20:52:51653 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11654 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51655 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
656 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
657 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04658 ),
Gabriel Charette87cc1af2018-04-25 20:52:51659 False,
Gabriel Charettea44975052017-08-21 23:14:04660 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57661 ),
662 (
Dave Tapuska98199b612019-07-10 13:30:44663 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57664 (
665 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02666 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57667 ),
668 True,
669 (),
Francois Doray43670e32017-09-27 12:40:38670 ),
671 (
Peter Kasting991618a62019-06-17 22:00:09672 r'/\bstd::stoi\b',
673 (
674 'std::stoi uses exceptions to communicate results. ',
675 'Use base::StringToInt() instead.',
676 ),
677 True,
678 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
679 ),
680 (
681 r'/\bstd::stol\b',
682 (
683 'std::stol uses exceptions to communicate results. ',
684 'Use base::StringToInt() instead.',
685 ),
686 True,
687 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
688 ),
689 (
690 r'/\bstd::stoul\b',
691 (
692 'std::stoul uses exceptions to communicate results. ',
693 'Use base::StringToUint() instead.',
694 ),
695 True,
696 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
697 ),
698 (
699 r'/\bstd::stoll\b',
700 (
701 'std::stoll uses exceptions to communicate results. ',
702 'Use base::StringToInt64() instead.',
703 ),
704 True,
705 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
706 ),
707 (
708 r'/\bstd::stoull\b',
709 (
710 'std::stoull uses exceptions to communicate results. ',
711 'Use base::StringToUint64() instead.',
712 ),
713 True,
714 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
715 ),
716 (
717 r'/\bstd::stof\b',
718 (
719 'std::stof uses exceptions to communicate results. ',
720 'For locale-independent values, e.g. reading numbers from disk',
721 'profiles, use base::StringToDouble().',
722 'For user-visible values, parse using ICU.',
723 ),
724 True,
725 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
726 ),
727 (
728 r'/\bstd::stod\b',
729 (
730 'std::stod uses exceptions to communicate results. ',
731 'For locale-independent values, e.g. reading numbers from disk',
732 'profiles, use base::StringToDouble().',
733 'For user-visible values, parse using ICU.',
734 ),
735 True,
736 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
737 ),
738 (
739 r'/\bstd::stold\b',
740 (
741 'std::stold uses exceptions to communicate results. ',
742 'For locale-independent values, e.g. reading numbers from disk',
743 'profiles, use base::StringToDouble().',
744 'For user-visible values, parse using ICU.',
745 ),
746 True,
747 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
748 ),
749 (
Daniel Bratell69334cc2019-03-26 11:07:45750 r'/\bstd::to_string\b',
751 (
752 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09753 'For locale-independent strings, e.g. writing numbers to disk',
754 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45755 'For user-visible strings, use base::FormatNumber() and',
756 'the related functions in base/i18n/number_formatting.h.',
757 ),
Peter Kasting991618a62019-06-17 22:00:09758 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21759 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45760 ),
761 (
762 r'/\bstd::shared_ptr\b',
763 (
764 'std::shared_ptr should not be used. Use scoped_refptr instead.',
765 ),
766 True,
Andreas Haas63f58792019-11-07 10:56:44767 [_THIRD_PARTY_EXCEPT_BLINK,
768 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
769 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21770 ),
771 (
Peter Kasting991618a62019-06-17 22:00:09772 r'/\bstd::weak_ptr\b',
773 (
774 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
775 ),
776 True,
777 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
778 ),
779 (
Daniel Bratell609102be2019-03-27 20:53:21780 r'/\blong long\b',
781 (
782 'long long is banned. Use stdint.h if you need a 64 bit number.',
783 ),
784 False, # Only a warning since it is already used.
785 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
786 ),
787 (
788 r'/\bstd::bind\b',
789 (
790 'std::bind is banned because of lifetime risks.',
791 'Use base::BindOnce or base::BindRepeating instead.',
792 ),
793 True,
794 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
795 ),
796 (
797 r'/\b#include <chrono>\b',
798 (
799 '<chrono> overlaps with Time APIs in base. Keep using',
800 'base classes.',
801 ),
802 True,
803 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
804 ),
805 (
806 r'/\b#include <exception>\b',
807 (
808 'Exceptions are banned and disabled in Chromium.',
809 ),
810 True,
811 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
812 ),
813 (
814 r'/\bstd::function\b',
815 (
816 'std::function is banned. Instead use base::Callback which directly',
817 'supports Chromium\'s weak pointers, ref counting and more.',
818 ),
Peter Kasting991618a62019-06-17 22:00:09819 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21820 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
821 ),
822 (
823 r'/\b#include <random>\b',
824 (
825 'Do not use any random number engines from <random>. Instead',
826 'use base::RandomBitGenerator.',
827 ),
828 True,
829 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
830 ),
831 (
832 r'/\bstd::ratio\b',
833 (
834 'std::ratio is banned by the Google Style Guide.',
835 ),
836 True,
837 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45838 ),
839 (
Francois Doray43670e32017-09-27 12:40:38840 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
841 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
842 (
843 'Use the new API in base/threading/thread_restrictions.h.',
844 ),
Gabriel Charette04b138f2018-08-06 00:03:22845 False,
Francois Doray43670e32017-09-27 12:40:38846 (),
847 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38848 (
danakj7a2b7082019-05-21 21:13:51849 r'/\bbase::Bind\(',
850 (
851 'Please use base::Bind{Once,Repeating} instead',
852 'of base::Bind. (crbug.com/714018)',
853 ),
854 False,
Erik Staaba737d7602019-11-25 18:41:07855 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51856 ),
857 (
858 r'/\bbase::Callback[<:]',
859 (
860 'Please use base::{Once,Repeating}Callback instead',
861 'of base::Callback. (crbug.com/714018)',
862 ),
863 False,
Erik Staaba737d7602019-11-25 18:41:07864 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51865 ),
866 (
867 r'/\bbase::Closure\b',
868 (
869 'Please use base::{Once,Repeating}Closure instead',
870 'of base::Closure. (crbug.com/714018)',
871 ),
872 False,
Erik Staaba737d7602019-11-25 18:41:07873 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51874 ),
875 (
Michael Giuffrida7f93d6922019-04-19 14:39:58876 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19877 (
878 'RunMessageLoop is deprecated, use RunLoop instead.',
879 ),
880 False,
881 (),
882 ),
883 (
Dave Tapuska98199b612019-07-10 13:30:44884 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19885 (
886 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
887 ),
888 False,
889 (),
890 ),
891 (
Dave Tapuska98199b612019-07-10 13:30:44892 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19893 (
894 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
895 "if you're convinced you need this.",
896 ),
897 False,
898 (),
899 ),
900 (
Dave Tapuska98199b612019-07-10 13:30:44901 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19902 (
903 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04904 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19905 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
906 'async events instead of flushing threads.',
907 ),
908 False,
909 (),
910 ),
911 (
912 r'MessageLoopRunner',
913 (
914 'MessageLoopRunner is deprecated, use RunLoop instead.',
915 ),
916 False,
917 (),
918 ),
919 (
Dave Tapuska98199b612019-07-10 13:30:44920 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19921 (
922 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
923 "gab@ if you found a use case where this is the only solution.",
924 ),
925 False,
926 (),
927 ),
928 (
Victor Costane48a2e82019-03-15 22:02:34929 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16930 (
Victor Costane48a2e82019-03-15 22:02:34931 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16932 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
933 ),
934 True,
935 (
936 r'^sql/initialization\.(cc|h)$',
937 r'^third_party/sqlite/.*\.(c|cc|h)$',
938 ),
939 ),
Matt Menke7f520a82018-03-28 21:38:37940 (
941 'net::URLFetcher',
942 (
943 'net::URLFetcher should no longer be used in content embedders. ',
944 'Instead, use network::SimpleURLLoader instead, which supports ',
945 'an out-of-process network stack. ',
946 'net::URLFetcher may still be used in binaries that do not embed',
947 'content.',
948 ),
Matt Menke59716d02018-04-05 12:45:53949 False,
Matt Menke7f520a82018-03-28 21:38:37950 (
Egor Paskoce145c42018-09-28 19:31:04951 r'^ios[\\/].*\.(cc|h)$',
952 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37953 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04954 r'^net[\\/].*\.(cc|h)$',
955 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43956 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37957 ),
958 ),
jdoerried7d10ab2018-04-27 10:46:13959 (
Dave Tapuska98199b612019-07-10 13:30:44960 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47961 (
962 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
963 'base::RandomShuffle instead.'
964 ),
965 True,
966 (),
967 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24968 (
969 'ios/web/public/test/http_server',
970 (
971 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
972 ),
973 False,
974 (),
975 ),
Robert Liao764c9492019-01-24 18:46:28976 (
977 'GetAddressOf',
978 (
979 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46980 'implicated in a few leaks. Use operator& instead. See ',
981 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28982 ),
983 True,
984 (),
985 ),
Antonio Gomes07300d02019-03-13 20:59:57986 (
987 'DEFINE_TYPE_CASTS',
988 (
989 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
990 '//third_party/blink/renderer/platform/casting.h.'
991 ),
992 True,
993 (
994 r'^third_party/blink/renderer/.*\.(cc|h)$',
995 ),
996 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38997 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45998 r'/\bIsHTML.+Element\(\b',
999 (
1000 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1001 ' helpers IsA<HTMLXXXXElement> from ',
1002 '//third_party/blink/renderer/platform/casting.h.'
1003 ),
1004 False,
1005 (
1006 r'^third_party/blink/renderer/.*\.(cc|h)$',
1007 ),
1008 ),
1009 (
1010 r'/\bToHTML.+Element(|OrNull)\(\b',
1011 (
1012 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1013 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1014 'and DynamicTo<HTMLXXXXElement> from ',
1015 '//third_party/blink/renderer/platform/casting.h.'
1016 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1017 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1018 ),
1019 False,
1020 (
1021 r'^third_party/blink/renderer/.*\.(cc|h)$',
1022 ),
1023 ),
1024 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371025 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381026 (
1027 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1028 ),
1029 True,
1030 (),
1031 ),
Ben Lewisa9514602019-04-29 17:53:051032 (
1033 'SHFileOperation',
1034 (
1035 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1036 'complex functions to achieve the same goals. Use IFileOperation for ',
1037 'any esoteric actions instead.'
1038 ),
1039 True,
1040 (),
1041 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181042 (
Cliff Smolinsky81951642019-04-30 21:39:511043 'StringFromGUID2',
1044 (
1045 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1046 'Use base::win::String16FromGUID instead.'
1047 ),
1048 True,
1049 (
1050 r'/base/win/win_util_unittest.cc'
1051 ),
1052 ),
1053 (
1054 'StringFromCLSID',
1055 (
1056 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1057 'Use base::win::String16FromGUID instead.'
1058 ),
1059 True,
1060 (
1061 r'/base/win/win_util_unittest.cc'
1062 ),
1063 ),
1064 (
Avi Drissman7382afa02019-04-29 23:27:131065 'kCFAllocatorNull',
1066 (
1067 'The use of kCFAllocatorNull with the NoCopy creation of ',
1068 'CoreFoundation types is prohibited.',
1069 ),
1070 True,
1071 (),
1072 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291073 (
1074 'mojo::ConvertTo',
1075 (
1076 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1077 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1078 'StringTraits if you would like to convert between custom types and',
1079 'the wire format of mojom types.'
1080 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221081 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291082 (
Wezf89dec092019-09-11 19:38:331083 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1084 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291085 r'^third_party/blink/.*\.(cc|h)$',
1086 r'^content/renderer/.*\.(cc|h)$',
1087 ),
1088 ),
Robert Liao1d78df52019-11-11 20:02:011089 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161090 'GetInterfaceProvider',
1091 (
1092 'InterfaceProvider is deprecated.',
1093 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1094 'or Platform::GetBrowserInterfaceBroker.'
1095 ),
1096 False,
1097 (),
1098 ),
1099 (
Robert Liao1d78df52019-11-11 20:02:011100 'CComPtr',
1101 (
1102 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1103 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1104 'details.'
1105 ),
1106 False,
1107 (),
1108 ),
Xiaohan Wang72bd2ba2020-02-18 21:38:201109 (
1110 r'/\b(IFACE|STD)METHOD_?\(',
1111 (
1112 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1113 'Instead, always use IFACEMETHODIMP in the declaration.'
1114 ),
1115 False,
1116 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1117 ),
[email protected]127f18ec2012-06-16 05:05:591118)
1119
Mario Sanchez Prada2472cab2019-09-18 10:58:311120# Format: Sequence of tuples containing:
1121# * String pattern or, if starting with a slash, a regular expression.
1122# * Sequence of strings to show when the pattern matches.
1123_DEPRECATED_MOJO_TYPES = (
1124 (
1125 r'/\bmojo::AssociatedBinding\b',
1126 (
1127 'mojo::AssociatedBinding<Interface> is deprecated.',
1128 'Use mojo::AssociatedReceiver<Interface> instead.',
1129 ),
1130 ),
1131 (
1132 r'/\bmojo::AssociatedBindingSet\b',
1133 (
1134 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1135 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1136 ),
1137 ),
1138 (
1139 r'/\bmojo::AssociatedInterfacePtr\b',
1140 (
1141 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1142 'Use mojo::AssociatedRemote<Interface> instead.',
1143 ),
1144 ),
1145 (
1146 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1147 (
1148 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1149 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1150 ),
1151 ),
1152 (
1153 r'/\bmojo::AssociatedInterfaceRequest\b',
1154 (
1155 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1156 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1157 ),
1158 ),
1159 (
1160 r'/\bmojo::Binding\b',
1161 (
1162 'mojo::Binding<Interface> is deprecated.',
1163 'Use mojo::Receiver<Interface> instead.',
1164 ),
1165 ),
1166 (
1167 r'/\bmojo::BindingSet\b',
1168 (
1169 'mojo::BindingSet<Interface> is deprecated.',
1170 'Use mojo::ReceiverSet<Interface> instead.',
1171 ),
1172 ),
1173 (
1174 r'/\bmojo::InterfacePtr\b',
1175 (
1176 'mojo::InterfacePtr<Interface> is deprecated.',
1177 'Use mojo::Remote<Interface> instead.',
1178 ),
1179 ),
1180 (
1181 r'/\bmojo::InterfacePtrInfo\b',
1182 (
1183 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1184 'Use mojo::PendingRemote<Interface> instead.',
1185 ),
1186 ),
1187 (
1188 r'/\bmojo::InterfaceRequest\b',
1189 (
1190 'mojo::InterfaceRequest<Interface> is deprecated.',
1191 'Use mojo::PendingReceiver<Interface> instead.',
1192 ),
1193 ),
1194 (
1195 r'/\bmojo::MakeRequest\b',
1196 (
1197 'mojo::MakeRequest is deprecated.',
1198 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1199 ),
1200 ),
1201 (
1202 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1203 (
1204 'mojo::MakeRequest is deprecated.',
1205 'Use mojo::AssociatedRemote::'
1206 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1207 ),
1208 ),
1209 (
1210 r'/\bmojo::MakeStrongBinding\b',
1211 (
1212 'mojo::MakeStrongBinding is deprecated.',
1213 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1214 'mojo::MakeSelfOwnedReceiver() instead.',
1215 ),
1216 ),
1217 (
1218 r'/\bmojo::MakeStrongAssociatedBinding\b',
1219 (
1220 'mojo::MakeStrongAssociatedBinding is deprecated.',
1221 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1222 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1223 ),
1224 ),
1225 (
1226 r'/\bmojo::StrongAssociatedBindingSet\b',
1227 (
1228 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1229 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1230 ),
1231 ),
1232 (
1233 r'/\bmojo::StrongBindingSet\b',
1234 (
1235 'mojo::StrongBindingSet<Interface> is deprecated.',
1236 'Use mojo::UniqueReceiverSet<Interface> instead.',
1237 ),
1238 ),
1239)
wnwenbdc444e2016-05-25 13:44:151240
mlamouria82272622014-09-16 18:45:041241_IPC_ENUM_TRAITS_DEPRECATED = (
1242 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501243 'See http://www.chromium.org/Home/chromium-security/education/'
1244 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041245
Stephen Martinis97a394142018-06-07 23:06:051246_LONG_PATH_ERROR = (
1247 'Some files included in this CL have file names that are too long (> 200'
1248 ' characters). If committed, these files will cause issues on Windows. See'
1249 ' https://crbug.com/612667 for more details.'
1250)
1251
Shenghua Zhangbfaa38b82017-11-16 21:58:021252_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041253 r".*[\\/]BuildHooksAndroidImpl\.java",
1254 r".*[\\/]LicenseContentProvider\.java",
1255 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281256 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021257]
[email protected]127f18ec2012-06-16 05:05:591258
Mohamed Heikald048240a2019-11-12 16:57:371259# List of image extensions that are used as resources in chromium.
1260_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1261
Sean Kau46e29bc2017-08-28 16:31:161262# These paths contain test data and other known invalid JSON files.
1263_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041264 r'test[\\/]data[\\/]',
1265 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1266 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041267 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431268 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161269]
1270
1271
[email protected]b00342e7f2013-03-26 16:21:541272_VALID_OS_MACROS = (
1273 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081274 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541275 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121276 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541277 'OS_BSD',
1278 'OS_CAT', # For testing.
1279 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041280 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541281 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371282 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541283 'OS_IOS',
1284 'OS_LINUX',
1285 'OS_MACOSX',
1286 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211287 'OS_NACL_NONSFI',
1288 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121289 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541290 'OS_OPENBSD',
1291 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371292 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541293 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541294 'OS_WIN',
1295)
1296
1297
agrievef32bcc72016-04-04 14:57:401298_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391299 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361300 'base/android/jni_generator/jni_generator.pydeps',
1301 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221302 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361303 'build/android/gyp/aar.pydeps',
1304 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271305 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361306 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381307 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111309 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361310 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361311 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361312 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111313 'build/android/gyp/create_app_bundle_apks.pydeps',
1314 'build/android/gyp/create_app_bundle.pydeps',
1315 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361316 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221317 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361318 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591319 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361320 'build/android/gyp/dex.pydeps',
1321 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361322 'build/android/gyp/filter_zip.pydeps',
1323 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361324 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361325 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581326 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361327 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261328 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve5853fbd2020-02-20 17:26:011329 'build/android/gyp/jetify_jar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361330 'build/android/gyp/jinja_template.pydeps',
1331 'build/android/gyp/lint.pydeps',
1332 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361333 'build/android/gyp/merge_manifest.pydeps',
1334 'build/android/gyp/prepare_resources.pydeps',
1335 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241336 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361337 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461338 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561339 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361340 'build/android/incremental_install/generate_android_manifest.pydeps',
1341 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221342 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401343 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041344 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361345 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411346 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051347 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191348 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431349 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021350 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401351]
1352
wnwenbdc444e2016-05-25 13:44:151353
agrievef32bcc72016-04-04 14:57:401354_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421355 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131356 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421357 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1358 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131359 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191360 ('third_party/blink/renderer/bindings/scripts/'
1361 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061362 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221363 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401364]
1365
wnwenbdc444e2016-05-25 13:44:151366
agrievef32bcc72016-04-04 14:57:401367_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1368
1369
Eric Boren6fd2b932018-01-25 15:05:081370# Bypass the AUTHORS check for these accounts.
1371_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591372 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451373 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591374 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521375 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1376 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041377 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271378 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041379 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301380 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081381
1382
Daniel Bratell65b033262019-04-23 08:17:061383def _IsCPlusPlusFile(input_api, file_path):
1384 """Returns True if this file contains C++-like code (and not Python,
1385 Go, Java, MarkDown, ...)"""
1386
1387 ext = input_api.os_path.splitext(file_path)[1]
1388 # This list is compatible with CppChecker.IsCppFile but we should
1389 # consider adding ".c" to it. If we do that we can use this function
1390 # at more places in the code.
1391 return ext in (
1392 '.h',
1393 '.cc',
1394 '.cpp',
1395 '.m',
1396 '.mm',
1397 )
1398
1399def _IsCPlusPlusHeaderFile(input_api, file_path):
1400 return input_api.os_path.splitext(file_path)[1] == ".h"
1401
1402
1403def _IsJavaFile(input_api, file_path):
1404 return input_api.os_path.splitext(file_path)[1] == ".java"
1405
1406
1407def _IsProtoFile(input_api, file_path):
1408 return input_api.os_path.splitext(file_path)[1] == ".proto"
1409
[email protected]55459852011-08-10 15:17:191410def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1411 """Attempts to prevent use of functions intended only for testing in
1412 non-testing code. For now this is just a best-effort implementation
1413 that ignores header files and may have some false positives. A
1414 better implementation would probably need a proper C++ parser.
1415 """
1416 # We only scan .cc files and the like, as the declaration of
1417 # for-testing functions in header files are hard to distinguish from
1418 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491419 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191420
jochenc0d4808c2015-07-27 09:25:421421 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191422 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091423 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191424 exclusion_pattern = input_api.re.compile(
1425 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1426 base_function_pattern, base_function_pattern))
1427
1428 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441429 black_list = (_EXCLUDED_PATHS +
1430 _TEST_CODE_EXCLUDED_PATHS +
1431 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191432 return input_api.FilterSourceFile(
1433 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491434 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191435 black_list=black_list)
1436
1437 problems = []
1438 for f in input_api.AffectedSourceFiles(FilterFile):
1439 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241440 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031441 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461442 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031443 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191444 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031445 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191446
1447 if problems:
[email protected]f7051d52013-04-02 18:31:421448 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031449 else:
1450 return []
[email protected]55459852011-08-10 15:17:191451
1452
Vaclav Brozek7dbc28c2018-03-27 08:35:231453def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1454 """This is a simplified version of
1455 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1456 """
1457 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1458 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1459 name_pattern = r'ForTest(s|ing)?'
1460 # Describes an occurrence of "ForTest*" inside a // comment.
1461 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1462 # Catch calls.
1463 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1464 # Ignore definitions. (Comments are ignored separately.)
1465 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1466
1467 problems = []
1468 sources = lambda x: input_api.FilterSourceFile(
1469 x,
1470 black_list=(('(?i).*test', r'.*\/junit\/')
1471 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491472 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231473 )
1474 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1475 local_path = f.LocalPath()
1476 is_inside_javadoc = False
1477 for line_number, line in f.ChangedContents():
1478 if is_inside_javadoc and javadoc_end_re.search(line):
1479 is_inside_javadoc = False
1480 if not is_inside_javadoc and javadoc_start_re.search(line):
1481 is_inside_javadoc = True
1482 if is_inside_javadoc:
1483 continue
1484 if (inclusion_re.search(line) and
1485 not comment_re.search(line) and
1486 not exclusion_re.search(line)):
1487 problems.append(
1488 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1489
1490 if problems:
1491 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1492 else:
1493 return []
1494
1495
[email protected]10689ca2011-09-02 02:31:541496def _CheckNoIOStreamInHeaders(input_api, output_api):
1497 """Checks to make sure no .h files include <iostream>."""
1498 files = []
1499 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1500 input_api.re.MULTILINE)
1501 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1502 if not f.LocalPath().endswith('.h'):
1503 continue
1504 contents = input_api.ReadFile(f)
1505 if pattern.search(contents):
1506 files.append(f)
1507
1508 if len(files):
yolandyandaabc6d2016-04-18 18:29:391509 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061510 'Do not #include <iostream> in header files, since it inserts static '
1511 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541512 '#include <ostream>. See http://crbug.com/94794',
1513 files) ]
1514 return []
1515
Danil Chapovalov3518f362018-08-11 16:13:431516def _CheckNoStrCatRedefines(input_api, output_api):
1517 """Checks no windows headers with StrCat redefined are included directly."""
1518 files = []
1519 pattern_deny = input_api.re.compile(
1520 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1521 input_api.re.MULTILINE)
1522 pattern_allow = input_api.re.compile(
1523 r'^#include\s"base/win/windows_defines.inc"',
1524 input_api.re.MULTILINE)
1525 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1526 contents = input_api.ReadFile(f)
1527 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1528 files.append(f.LocalPath())
1529
1530 if len(files):
1531 return [output_api.PresubmitError(
1532 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1533 'directly since they pollute code with StrCat macro. Instead, '
1534 'include matching header from base/win. See http://crbug.com/856536',
1535 files) ]
1536 return []
1537
[email protected]10689ca2011-09-02 02:31:541538
[email protected]72df4e782012-06-21 16:28:181539def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521540 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181541 problems = []
1542 for f in input_api.AffectedFiles():
1543 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1544 continue
1545
1546 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041547 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181548 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1549
1550 if not problems:
1551 return []
1552 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1553 '\n'.join(problems))]
1554
Dominic Battre033531052018-09-24 15:45:341555def _CheckNoDISABLETypoInTests(input_api, output_api):
1556 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1557
1558 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1559 instead of DISABLED_. To filter false positives, reports are only generated
1560 if a corresponding MAYBE_ line exists.
1561 """
1562 problems = []
1563
1564 # The following two patterns are looked for in tandem - is a test labeled
1565 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1566 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1567 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1568
1569 # This is for the case that a test is disabled on all platforms.
1570 full_disable_pattern = input_api.re.compile(
1571 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1572 input_api.re.MULTILINE)
1573
Katie Df13948e2018-09-25 07:33:441574 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341575 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1576 continue
1577
1578 # Search for MABYE_, DISABLE_ pairs.
1579 disable_lines = {} # Maps of test name to line number.
1580 maybe_lines = {}
1581 for line_num, line in f.ChangedContents():
1582 disable_match = disable_pattern.search(line)
1583 if disable_match:
1584 disable_lines[disable_match.group(1)] = line_num
1585 maybe_match = maybe_pattern.search(line)
1586 if maybe_match:
1587 maybe_lines[maybe_match.group(1)] = line_num
1588
1589 # Search for DISABLE_ occurrences within a TEST() macro.
1590 disable_tests = set(disable_lines.keys())
1591 maybe_tests = set(maybe_lines.keys())
1592 for test in disable_tests.intersection(maybe_tests):
1593 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1594
1595 contents = input_api.ReadFile(f)
1596 full_disable_match = full_disable_pattern.search(contents)
1597 if full_disable_match:
1598 problems.append(' %s' % f.LocalPath())
1599
1600 if not problems:
1601 return []
1602 return [
1603 output_api.PresubmitPromptWarning(
1604 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1605 '\n'.join(problems))
1606 ]
1607
[email protected]72df4e782012-06-21 16:28:181608
danakj61c1aa22015-10-26 19:55:521609def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571610 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521611 errors = []
1612 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1613 input_api.re.MULTILINE)
1614 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1615 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1616 continue
1617 for lnum, line in f.ChangedContents():
1618 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171619 errors.append(output_api.PresubmitError(
1620 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571621 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171622 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521623 return errors
1624
1625
Makoto Shimazu3ad422cd2019-05-08 02:35:141626def _FindHistogramNameInChunk(histogram_name, chunk):
1627 """Tries to find a histogram name or prefix in a line.
1628
1629 Returns the existence of the histogram name, or None if it needs more chunk
1630 to determine."""
mcasasb7440c282015-02-04 14:52:191631 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1632 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141633 if '<affected-histogram' in chunk:
1634 # If the tag is not completed, needs more chunk to get the name.
1635 if not '>' in chunk:
1636 return None
1637 if not 'name="' in chunk:
1638 return False
1639 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1640 # expect the only attribute is the name.
1641 histogram_prefix = chunk.split('"')[1]
1642 return histogram_prefix in histogram_name
1643 # Typically the whole histogram name should in the line.
1644 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191645
1646
1647def _CheckUmaHistogramChanges(input_api, output_api):
1648 """Check that UMA histogram names in touched lines can still be found in other
1649 lines of the patch or in histograms.xml. Note that this check would not catch
1650 the reverse: changes in histograms.xml not matched in the code itself."""
1651 touched_histograms = []
1652 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471653 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1654 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1655 name_pattern = r'"(.*?)"'
1656 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1657 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1658 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1659 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1660 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171661 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191662 for f in input_api.AffectedFiles():
1663 # If histograms.xml itself is modified, keep the modified lines for later.
1664 if f.LocalPath().endswith(('histograms.xml')):
1665 histograms_xml_modifications = f.ChangedContents()
1666 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471667 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1668 single_line_re = single_line_c_re
1669 split_line_prefix_re = split_line_c_prefix_re
1670 elif f.LocalPath().endswith(('java')):
1671 single_line_re = single_line_java_re
1672 split_line_prefix_re = split_line_java_prefix_re
1673 else:
mcasasb7440c282015-02-04 14:52:191674 continue
1675 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171676 if last_line_matched_prefix:
1677 suffix_found = split_line_suffix_re.search(line)
1678 if suffix_found :
1679 touched_histograms.append([suffix_found.group(1), f, line_num])
1680 last_line_matched_prefix = False
1681 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061682 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191683 if found:
1684 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171685 continue
1686 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191687
1688 # Search for the touched histogram names in the local modifications to
1689 # histograms.xml, and, if not found, on the base histograms.xml file.
1690 unmatched_histograms = []
1691 for histogram_info in touched_histograms:
1692 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141693 chunk = ''
mcasasb7440c282015-02-04 14:52:191694 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141695 chunk += line
1696 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1697 if histogram_name_found is None:
1698 continue
1699 chunk = ''
mcasasb7440c282015-02-04 14:52:191700 if histogram_name_found:
1701 break
1702 if not histogram_name_found:
1703 unmatched_histograms.append(histogram_info)
1704
eromanb90c82e7e32015-04-01 15:13:491705 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191706 problems = []
1707 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491708 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191709 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451710 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191711 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141712 chunk = ''
mcasasb7440c282015-02-04 14:52:191713 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141714 chunk += line
1715 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1716 chunk)
1717 if histogram_name_found is None:
1718 continue
1719 chunk = ''
mcasasb7440c282015-02-04 14:52:191720 if histogram_name_found:
1721 break
1722 if not histogram_name_found:
1723 problems.append(' [%s:%d] %s' %
1724 (f.LocalPath(), line_num, histogram_name))
1725
1726 if not problems:
1727 return []
1728 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1729 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491730 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191731
wnwenbdc444e2016-05-25 13:44:151732
yolandyandaabc6d2016-04-18 18:29:391733def _CheckFlakyTestUsage(input_api, output_api):
1734 """Check that FlakyTest annotation is our own instead of the android one"""
1735 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1736 files = []
1737 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1738 if f.LocalPath().endswith('Test.java'):
1739 if pattern.search(input_api.ReadFile(f)):
1740 files.append(f)
1741 if len(files):
1742 return [output_api.PresubmitError(
1743 'Use org.chromium.base.test.util.FlakyTest instead of '
1744 'android.test.FlakyTest',
1745 files)]
1746 return []
mcasasb7440c282015-02-04 14:52:191747
wnwenbdc444e2016-05-25 13:44:151748
[email protected]8ea5d4b2011-09-13 21:49:221749def _CheckNoNewWStrings(input_api, output_api):
1750 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271751 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221752 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201753 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571754 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341755 '/win/' in f.LocalPath() or
1756 'chrome_elf' in f.LocalPath() or
1757 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201758 continue
[email protected]8ea5d4b2011-09-13 21:49:221759
[email protected]a11dbe9b2012-08-07 01:32:581760 allowWString = False
[email protected]b5c24292011-11-28 14:38:201761 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581762 if 'presubmit: allow wstring' in line:
1763 allowWString = True
1764 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271765 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581766 allowWString = False
1767 else:
1768 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221769
[email protected]55463aa62011-10-12 00:48:271770 if not problems:
1771 return []
1772 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581773 ' If you are calling a cross-platform API that accepts a wstring, '
1774 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271775 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221776
1777
[email protected]2a8ac9c2011-10-19 17:20:441778def _CheckNoDEPSGIT(input_api, output_api):
1779 """Make sure .DEPS.git is never modified manually."""
1780 if any(f.LocalPath().endswith('.DEPS.git') for f in
1781 input_api.AffectedFiles()):
1782 return [output_api.PresubmitError(
1783 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1784 'automated system based on what\'s in DEPS and your changes will be\n'
1785 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501786 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1787 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441788 'for more information')]
1789 return []
1790
1791
tandriief664692014-09-23 14:51:471792def _CheckValidHostsInDEPS(input_api, output_api):
1793 """Checks that DEPS file deps are from allowed_hosts."""
1794 # Run only if DEPS file has been modified to annoy fewer bystanders.
1795 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1796 return []
1797 # Outsource work to gclient verify
1798 try:
John Budorickf20c0042019-04-25 23:23:401799 gclient_path = input_api.os_path.join(
1800 input_api.PresubmitLocalPath(),
1801 'third_party', 'depot_tools', 'gclient.py')
1802 input_api.subprocess.check_output(
1803 [input_api.python_executable, gclient_path, 'verify'],
1804 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471805 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201806 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471807 return [output_api.PresubmitError(
1808 'DEPS file must have only git dependencies.',
1809 long_text=error.output)]
1810
1811
Mario Sanchez Prada2472cab2019-09-18 10:58:311812def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1813 type_name, message):
1814 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1815
1816 Returns an string composed of the name of the file, the line number where the
1817 match has been found and the additional text passed as |message| in case the
1818 target type name matches the text inside the line passed as parameter.
1819 """
1820 matched = False
1821 if type_name[0:1] == '/':
1822 regex = type_name[1:]
1823 if input_api.re.search(regex, line):
1824 matched = True
1825 elif type_name in line:
1826 matched = True
1827
1828 result = []
1829 if matched:
1830 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1831 for message_line in message:
1832 result.append(' %s' % message_line)
1833
1834 return result
1835
1836
[email protected]127f18ec2012-06-16 05:05:591837def _CheckNoBannedFunctions(input_api, output_api):
1838 """Make sure that banned functions are not used."""
1839 warnings = []
1840 errors = []
1841
wnwenbdc444e2016-05-25 13:44:151842 def IsBlacklisted(affected_file, blacklist):
1843 local_path = affected_file.LocalPath()
1844 for item in blacklist:
1845 if input_api.re.match(item, local_path):
1846 return True
1847 return False
1848
Peter K. Lee6c03ccff2019-07-15 14:40:051849 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541850 local_path = affected_file.LocalPath()
1851 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1852 return False
1853 basename = input_api.os_path.basename(local_path)
1854 if 'ios' in basename.split('_'):
1855 return True
1856 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1857 if sep and 'ios' in local_path.split(sep):
1858 return True
1859 return False
1860
wnwenbdc444e2016-05-25 13:44:151861 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311862 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1863 func_name, message)
1864 if problems:
wnwenbdc444e2016-05-25 13:44:151865 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311866 errors.extend(problems)
1867 else:
1868 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151869
Eric Stevensona9a980972017-09-23 00:04:411870 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1871 for f in input_api.AffectedFiles(file_filter=file_filter):
1872 for line_num, line in f.ChangedContents():
1873 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1874 CheckForMatch(f, line_num, line, func_name, message, error)
1875
[email protected]127f18ec2012-06-16 05:05:591876 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1877 for f in input_api.AffectedFiles(file_filter=file_filter):
1878 for line_num, line in f.ChangedContents():
1879 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151880 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591881
Peter K. Lee6c03ccff2019-07-15 14:40:051882 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541883 for line_num, line in f.ChangedContents():
1884 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1885 CheckForMatch(f, line_num, line, func_name, message, error)
1886
Peter K. Lee6c03ccff2019-07-15 14:40:051887 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1888 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1889 for line_num, line in f.ChangedContents():
1890 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1891 CheckForMatch(f, line_num, line, func_name, message, error)
1892
[email protected]127f18ec2012-06-16 05:05:591893 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1894 for f in input_api.AffectedFiles(file_filter=file_filter):
1895 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491896 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491897 if IsBlacklisted(f, excluded_paths):
1898 continue
wnwenbdc444e2016-05-25 13:44:151899 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591900
1901 result = []
1902 if (warnings):
1903 result.append(output_api.PresubmitPromptWarning(
1904 'Banned functions were used.\n' + '\n'.join(warnings)))
1905 if (errors):
1906 result.append(output_api.PresubmitError(
1907 'Banned functions were used.\n' + '\n'.join(errors)))
1908 return result
1909
1910
Michael Thiessen44457642020-02-06 00:24:151911def _CheckAndroidNoBannedImports(input_api, output_api):
1912 """Make sure that banned java imports are not used."""
1913 errors = []
1914
1915 def IsException(path, exceptions):
1916 for exception in exceptions:
1917 if (path.startswith(exception)):
1918 return True
1919 return False
1920
1921 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1922 for f in input_api.AffectedFiles(file_filter=file_filter):
1923 for line_num, line in f.ChangedContents():
1924 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1925 if IsException(f.LocalPath(), exceptions):
1926 continue;
1927 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1928 'import ' + import_name, message)
1929 if problems:
1930 errors.extend(problems)
1931 result = []
1932 if (errors):
1933 result.append(output_api.PresubmitError(
1934 'Banned imports were used.\n' + '\n'.join(errors)))
1935 return result
1936
1937
Mario Sanchez Prada2472cab2019-09-18 10:58:311938def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1939 """Make sure that old Mojo types are not used."""
1940 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571941 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311942
Mario Sanchez Pradaaab91382019-12-19 08:57:091943 # For any path that is not an "ok" or an "error" path, a warning will be
1944 # raised if deprecated mojo types are found.
1945 ok_paths = ['components/arc']
1946 error_paths = ['third_party/blink', 'content']
1947
Mario Sanchez Prada2472cab2019-09-18 10:58:311948 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1949 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571950 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091951 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311952 continue
1953
1954 for line_num, line in f.ChangedContents():
1955 for func_name, message in _DEPRECATED_MOJO_TYPES:
1956 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1957 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571958
Mario Sanchez Prada2472cab2019-09-18 10:58:311959 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091960 # Raise errors inside |error_paths| and warnings everywhere else.
1961 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571962 errors.extend(problems)
1963 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311964 warnings.extend(problems)
1965
1966 result = []
1967 if (warnings):
1968 result.append(output_api.PresubmitPromptWarning(
1969 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571970 if (errors):
1971 result.append(output_api.PresubmitError(
1972 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311973 return result
1974
1975
[email protected]6c063c62012-07-11 19:11:061976def _CheckNoPragmaOnce(input_api, output_api):
1977 """Make sure that banned functions are not used."""
1978 files = []
1979 pattern = input_api.re.compile(r'^#pragma\s+once',
1980 input_api.re.MULTILINE)
1981 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1982 if not f.LocalPath().endswith('.h'):
1983 continue
1984 contents = input_api.ReadFile(f)
1985 if pattern.search(contents):
1986 files.append(f)
1987
1988 if files:
1989 return [output_api.PresubmitError(
1990 'Do not use #pragma once in header files.\n'
1991 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1992 files)]
1993 return []
1994
[email protected]127f18ec2012-06-16 05:05:591995
[email protected]e7479052012-09-19 00:26:121996def _CheckNoTrinaryTrueFalse(input_api, output_api):
1997 """Checks to make sure we don't introduce use of foo ? true : false."""
1998 problems = []
1999 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2000 for f in input_api.AffectedFiles():
2001 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2002 continue
2003
2004 for line_num, line in f.ChangedContents():
2005 if pattern.match(line):
2006 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2007
2008 if not problems:
2009 return []
2010 return [output_api.PresubmitPromptWarning(
2011 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2012 '\n'.join(problems))]
2013
2014
[email protected]55f9f382012-07-31 11:02:182015def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282016 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182017 change. Breaking - rules is an error, breaking ! rules is a
2018 warning.
2019 """
mohan.reddyf21db962014-10-16 12:26:472020 import sys
[email protected]55f9f382012-07-31 11:02:182021 # We need to wait until we have an input_api object and use this
2022 # roundabout construct to import checkdeps because this file is
2023 # eval-ed and thus doesn't have __file__.
2024 original_sys_path = sys.path
2025 try:
2026 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472027 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182028 import checkdeps
[email protected]55f9f382012-07-31 11:02:182029 from rules import Rule
2030 finally:
2031 # Restore sys.path to what it was before.
2032 sys.path = original_sys_path
2033
2034 added_includes = []
rhalavati08acd232017-04-03 07:23:282035 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242036 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182037 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062038 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502039 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082040 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062041 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502042 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082043 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062044 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502045 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082046 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182047
[email protected]26385172013-05-09 23:11:352048 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182049
2050 error_descriptions = []
2051 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282052 error_subjects = set()
2053 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182054 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2055 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082056 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182057 description_with_path = '%s\n %s' % (path, rule_description)
2058 if rule_type == Rule.DISALLOW:
2059 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282060 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182061 else:
2062 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282063 warning_subjects.add("#includes")
2064
2065 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2066 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082067 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282068 description_with_path = '%s\n %s' % (path, rule_description)
2069 if rule_type == Rule.DISALLOW:
2070 error_descriptions.append(description_with_path)
2071 error_subjects.add("imports")
2072 else:
2073 warning_descriptions.append(description_with_path)
2074 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182075
Jinsuk Kim5a092672017-10-24 22:42:242076 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022077 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082078 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242079 description_with_path = '%s\n %s' % (path, rule_description)
2080 if rule_type == Rule.DISALLOW:
2081 error_descriptions.append(description_with_path)
2082 error_subjects.add("imports")
2083 else:
2084 warning_descriptions.append(description_with_path)
2085 warning_subjects.add("imports")
2086
[email protected]55f9f382012-07-31 11:02:182087 results = []
2088 if error_descriptions:
2089 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282090 'You added one or more %s that violate checkdeps rules.'
2091 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182092 error_descriptions))
2093 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422094 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282095 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182096 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282097 '%s? See relevant DEPS file(s) for details and contacts.' %
2098 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182099 warning_descriptions))
2100 return results
2101
2102
[email protected]fbcafe5a2012-08-08 15:31:222103def _CheckFilePermissions(input_api, output_api):
2104 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152105 if input_api.platform == 'win32':
2106 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292107 checkperms_tool = input_api.os_path.join(
2108 input_api.PresubmitLocalPath(),
2109 'tools', 'checkperms', 'checkperms.py')
2110 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472111 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392112 with input_api.CreateTemporaryFile() as file_list:
2113 for f in input_api.AffectedFiles():
2114 # checkperms.py file/directory arguments must be relative to the
2115 # repository.
2116 file_list.write(f.LocalPath() + '\n')
2117 file_list.close()
2118 args += ['--file-list', file_list.name]
2119 try:
2120 input_api.subprocess.check_output(args)
2121 return []
2122 except input_api.subprocess.CalledProcessError as error:
2123 return [output_api.PresubmitError(
2124 'checkperms.py failed:',
2125 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222126
2127
robertocn832f5992017-01-04 19:01:302128def _CheckTeamTags(input_api, output_api):
2129 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2130 checkteamtags_tool = input_api.os_path.join(
2131 input_api.PresubmitLocalPath(),
2132 'tools', 'checkteamtags', 'checkteamtags.py')
2133 args = [input_api.python_executable, checkteamtags_tool,
2134 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222135 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302136 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2137 'OWNERS']
2138 try:
2139 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052140 warnings = input_api.subprocess.check_output(args + files).splitlines()
2141 if warnings:
2142 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302143 return []
2144 except input_api.subprocess.CalledProcessError as error:
2145 return [output_api.PresubmitError(
2146 'checkteamtags.py failed:',
2147 long_text=error.output)]
2148
2149
[email protected]c8278b32012-10-30 20:35:492150def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2151 """Makes sure we don't include ui/aura/window_property.h
2152 in header files.
2153 """
2154 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2155 errors = []
2156 for f in input_api.AffectedFiles():
2157 if not f.LocalPath().endswith('.h'):
2158 continue
2159 for line_num, line in f.ChangedContents():
2160 if pattern.match(line):
2161 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2162
2163 results = []
2164 if errors:
2165 results.append(output_api.PresubmitError(
2166 'Header files should not include ui/aura/window_property.h', errors))
2167 return results
2168
2169
[email protected]70ca77752012-11-20 03:45:032170def _CheckForVersionControlConflictsInFile(input_api, f):
2171 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2172 errors = []
2173 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162174 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232175 # First-level headers in markdown look a lot like version control
2176 # conflict markers. http://daringfireball.net/projects/markdown/basics
2177 continue
[email protected]70ca77752012-11-20 03:45:032178 if pattern.match(line):
2179 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2180 return errors
2181
2182
2183def _CheckForVersionControlConflicts(input_api, output_api):
2184 """Usually this is not intentional and will cause a compile failure."""
2185 errors = []
2186 for f in input_api.AffectedFiles():
2187 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2188
2189 results = []
2190 if errors:
2191 results.append(output_api.PresubmitError(
2192 'Version control conflict markers found, please resolve.', errors))
2193 return results
2194
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202195
estadee17314a02017-01-12 16:22:162196def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2197 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2198 errors = []
2199 for f in input_api.AffectedFiles():
2200 for line_num, line in f.ChangedContents():
2201 if pattern.search(line):
2202 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2203
2204 results = []
2205 if errors:
2206 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502207 'Found Google support URL addressed by answer number. Please replace '
2208 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162209 return results
2210
[email protected]70ca77752012-11-20 03:45:032211
[email protected]06e6d0ff2012-12-11 01:36:442212def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2213 def FilterFile(affected_file):
2214 """Filter function for use with input_api.AffectedSourceFiles,
2215 below. This filters out everything except non-test files from
2216 top-level directories that generally speaking should not hard-code
2217 service URLs (e.g. src/android_webview/, src/content/ and others).
2218 """
2219 return input_api.FilterSourceFile(
2220 affected_file,
Egor Paskoce145c42018-09-28 19:31:042221 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442222 black_list=(_EXCLUDED_PATHS +
2223 _TEST_CODE_EXCLUDED_PATHS +
2224 input_api.DEFAULT_BLACK_LIST))
2225
reillyi38965732015-11-16 18:27:332226 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2227 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462228 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2229 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442230 problems = [] # items are (filename, line_number, line)
2231 for f in input_api.AffectedSourceFiles(FilterFile):
2232 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462233 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442234 problems.append((f.LocalPath(), line_num, line))
2235
2236 if problems:
[email protected]f7051d52013-04-02 18:31:422237 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442238 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582239 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442240 [' %s:%d: %s' % (
2241 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032242 else:
2243 return []
[email protected]06e6d0ff2012-12-11 01:36:442244
2245
James Cook6b6597c2019-11-06 22:05:292246def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2247 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2248 def FileFilter(affected_file):
2249 """Includes directories known to be Chrome OS only."""
2250 return input_api.FilterSourceFile(
2251 affected_file,
2252 white_list=('^ash/',
2253 '^chromeos/', # Top-level src/chromeos.
2254 '/chromeos/', # Any path component.
2255 '^components/arc',
2256 '^components/exo'),
2257 black_list=(input_api.DEFAULT_BLACK_LIST))
2258
2259 prefs = []
2260 priority_prefs = []
2261 for f in input_api.AffectedFiles(file_filter=FileFilter):
2262 for line_num, line in f.ChangedContents():
2263 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2264 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2265 prefs.append(' %s' % line)
2266 if input_api.re.search(
2267 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2268 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2269 priority_prefs.append(' %s' % line)
2270
2271 results = []
2272 if (prefs):
2273 results.append(output_api.PresubmitPromptWarning(
2274 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2275 'by browser sync settings. If these prefs should be controlled by OS '
2276 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2277 if (priority_prefs):
2278 results.append(output_api.PresubmitPromptWarning(
2279 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2280 'controlled by browser sync settings. If these prefs should be '
2281 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2282 'instead.\n' + '\n'.join(prefs)))
2283 return results
2284
2285
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492286# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272287def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2288 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312289 The native_client_sdk directory is excluded because it has auto-generated PNG
2290 files for documentation.
[email protected]d2530012013-01-25 16:39:272291 """
[email protected]d2530012013-01-25 16:39:272292 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492293 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042294 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312295 file_filter = lambda f: input_api.FilterSourceFile(
2296 f, white_list=white_list, black_list=black_list)
2297 for f in input_api.AffectedFiles(include_deletes=False,
2298 file_filter=file_filter):
2299 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272300
2301 results = []
2302 if errors:
2303 results.append(output_api.PresubmitError(
2304 'The name of PNG files should not have abbreviations. \n'
2305 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2306 'Contact [email protected] if you have questions.', errors))
2307 return results
2308
2309
Daniel Cheng4dcdb6b2017-04-13 08:30:172310def _ExtractAddRulesFromParsedDeps(parsed_deps):
2311 """Extract the rules that add dependencies from a parsed DEPS file.
2312
2313 Args:
2314 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2315 add_rules = set()
2316 add_rules.update([
2317 rule[1:] for rule in parsed_deps.get('include_rules', [])
2318 if rule.startswith('+') or rule.startswith('!')
2319 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502320 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172321 {}).iteritems():
2322 add_rules.update([
2323 rule[1:] for rule in rules
2324 if rule.startswith('+') or rule.startswith('!')
2325 ])
2326 return add_rules
2327
2328
2329def _ParseDeps(contents):
2330 """Simple helper for parsing DEPS files."""
2331 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172332 class _VarImpl:
2333
2334 def __init__(self, local_scope):
2335 self._local_scope = local_scope
2336
2337 def Lookup(self, var_name):
2338 """Implements the Var syntax."""
2339 try:
2340 return self._local_scope['vars'][var_name]
2341 except KeyError:
2342 raise Exception('Var is not defined: %s' % var_name)
2343
2344 local_scope = {}
2345 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172346 'Var': _VarImpl(local_scope).Lookup,
2347 }
2348 exec contents in global_scope, local_scope
2349 return local_scope
2350
2351
2352def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082353 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412354 a set of DEPS entries that we should look up.
2355
2356 For a directory (rather than a specific filename) we fake a path to
2357 a specific filename by adding /DEPS. This is chosen as a file that
2358 will seldom or never be subject to per-file include_rules.
2359 """
[email protected]2b438d62013-11-14 17:54:142360 # We ignore deps entries on auto-generated directories.
2361 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082362
Daniel Cheng4dcdb6b2017-04-13 08:30:172363 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2364 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2365
2366 added_deps = new_deps.difference(old_deps)
2367
[email protected]2b438d62013-11-14 17:54:142368 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172369 for added_dep in added_deps:
2370 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2371 continue
2372 # Assume that a rule that ends in .h is a rule for a specific file.
2373 if added_dep.endswith('.h'):
2374 results.add(added_dep)
2375 else:
2376 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082377 return results
2378
2379
[email protected]e871964c2013-05-13 14:14:552380def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2381 """When a dependency prefixed with + is added to a DEPS file, we
2382 want to make sure that the change is reviewed by an OWNER of the
2383 target file or directory, to avoid layering violations from being
2384 introduced. This check verifies that this happens.
2385 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172386 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242387
2388 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492389 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242390 for f in input_api.AffectedFiles(include_deletes=False,
2391 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552392 filename = input_api.os_path.basename(f.LocalPath())
2393 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172394 virtual_depended_on_files.update(_CalculateAddedDeps(
2395 input_api.os_path,
2396 '\n'.join(f.OldContents()),
2397 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552398
[email protected]e871964c2013-05-13 14:14:552399 if not virtual_depended_on_files:
2400 return []
2401
2402 if input_api.is_committing:
2403 if input_api.tbr:
2404 return [output_api.PresubmitNotifyResult(
2405 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272406 if input_api.dry_run:
2407 return [output_api.PresubmitNotifyResult(
2408 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552409 if not input_api.change.issue:
2410 return [output_api.PresubmitError(
2411 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402412 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552413 output = output_api.PresubmitError
2414 else:
2415 output = output_api.PresubmitNotifyResult
2416
2417 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502418 owner_email, reviewers = (
2419 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2420 input_api,
2421 owners_db.email_regexp,
2422 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552423
2424 owner_email = owner_email or input_api.change.author_email
2425
[email protected]de4f7d22013-05-23 14:27:462426 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512427 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462428 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552429 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2430 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412431
2432 # We strip the /DEPS part that was added by
2433 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2434 # directory.
2435 def StripDeps(path):
2436 start_deps = path.rfind('/DEPS')
2437 if start_deps != -1:
2438 return path[:start_deps]
2439 else:
2440 return path
2441 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552442 for path in missing_files]
2443
2444 if unapproved_dependencies:
2445 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152446 output('You need LGTM from owners of depends-on paths in DEPS that were '
2447 'modified in this CL:\n %s' %
2448 '\n '.join(sorted(unapproved_dependencies)))]
2449 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2450 output_list.append(output(
2451 'Suggested missing target path OWNERS:\n %s' %
2452 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552453 return output_list
2454
2455 return []
2456
2457
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492458# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402459def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492460 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402461 black_list = (_EXCLUDED_PATHS +
2462 _TEST_CODE_EXCLUDED_PATHS +
2463 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042464 (r"^base[\\/]logging\.h$",
2465 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222466 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042467 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2468 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2469 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122470 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182471 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152472 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032473 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152474 r"^chrome[\\/]chrome_cleaner[\\/].*",
2475 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2476 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042477 r"^chromecast[\\/]",
2478 r"^cloud_print[\\/]",
2479 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482480 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042481 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312482 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042483 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462484 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042485 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462486 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042487 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252488 r"gl_helper_benchmark\.cc$",
Robert Flackc0ee0272020-02-26 05:57:402489 r"^content[\\/]renderer[\\/]render_frame_impl.cc$",
Egor Paskoce145c42018-09-28 19:31:042490 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2491 r"^courgette[\\/]courgette_tool\.cc$",
2492 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272493 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002494 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332495 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042496 r"^ipc[\\/]ipc_logging\.cc$",
2497 r"^native_client_sdk[\\/]",
2498 r"^remoting[\\/]base[\\/]logging\.h$",
2499 r"^remoting[\\/]host[\\/].*",
2500 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062501 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332502 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042503 r"^tools[\\/]",
2504 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2505 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332506 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402507 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492508 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402509
thomasanderson625d3932017-03-29 07:16:582510 log_info = set([])
2511 printf = set([])
[email protected]85218562013-11-22 07:41:402512
2513 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582514 for _, line in f.ChangedContents():
2515 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2516 log_info.add(f.LocalPath())
2517 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2518 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372519
thomasanderson625d3932017-03-29 07:16:582520 if input_api.re.search(r"\bprintf\(", line):
2521 printf.add(f.LocalPath())
2522 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2523 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402524
2525 if log_info:
2526 return [output_api.PresubmitError(
2527 'These files spam the console log with LOG(INFO):',
2528 items=log_info)]
2529 if printf:
2530 return [output_api.PresubmitError(
2531 'These files spam the console log with printf/fprintf:',
2532 items=printf)]
2533 return []
2534
2535
[email protected]49aa76a2013-12-04 06:59:162536def _CheckForAnonymousVariables(input_api, output_api):
2537 """These types are all expected to hold locks while in scope and
2538 so should never be anonymous (which causes them to be immediately
2539 destroyed)."""
2540 they_who_must_be_named = [
2541 'base::AutoLock',
2542 'base::AutoReset',
2543 'base::AutoUnlock',
2544 'SkAutoAlphaRestore',
2545 'SkAutoBitmapShaderInstall',
2546 'SkAutoBlitterChoose',
2547 'SkAutoBounderCommit',
2548 'SkAutoCallProc',
2549 'SkAutoCanvasRestore',
2550 'SkAutoCommentBlock',
2551 'SkAutoDescriptor',
2552 'SkAutoDisableDirectionCheck',
2553 'SkAutoDisableOvalCheck',
2554 'SkAutoFree',
2555 'SkAutoGlyphCache',
2556 'SkAutoHDC',
2557 'SkAutoLockColors',
2558 'SkAutoLockPixels',
2559 'SkAutoMalloc',
2560 'SkAutoMaskFreeImage',
2561 'SkAutoMutexAcquire',
2562 'SkAutoPathBoundsUpdate',
2563 'SkAutoPDFRelease',
2564 'SkAutoRasterClipValidate',
2565 'SkAutoRef',
2566 'SkAutoTime',
2567 'SkAutoTrace',
2568 'SkAutoUnref',
2569 ]
2570 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2571 # bad: base::AutoLock(lock.get());
2572 # not bad: base::AutoLock lock(lock.get());
2573 bad_pattern = input_api.re.compile(anonymous)
2574 # good: new base::AutoLock(lock.get())
2575 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2576 errors = []
2577
2578 for f in input_api.AffectedFiles():
2579 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2580 continue
2581 for linenum, line in f.ChangedContents():
2582 if bad_pattern.search(line) and not good_pattern.search(line):
2583 errors.append('%s:%d' % (f.LocalPath(), linenum))
2584
2585 if errors:
2586 return [output_api.PresubmitError(
2587 'These lines create anonymous variables that need to be named:',
2588 items=errors)]
2589 return []
2590
2591
Peter Kasting4844e46e2018-02-23 07:27:102592def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532593 # Returns whether |template_str| is of the form <T, U...> for some types T
2594 # and U. Assumes that |template_str| is already in the form <...>.
2595 def HasMoreThanOneArg(template_str):
2596 # Level of <...> nesting.
2597 nesting = 0
2598 for c in template_str:
2599 if c == '<':
2600 nesting += 1
2601 elif c == '>':
2602 nesting -= 1
2603 elif c == ',' and nesting == 1:
2604 return True
2605 return False
2606
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492607 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102608 sources = lambda affected_file: input_api.FilterSourceFile(
2609 affected_file,
2610 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2611 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492612 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552613
2614 # Pattern to capture a single "<...>" block of template arguments. It can
2615 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2616 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2617 # latter would likely require counting that < and > match, which is not
2618 # expressible in regular languages. Should the need arise, one can introduce
2619 # limited counting (matching up to a total number of nesting depth), which
2620 # should cover all practical cases for already a low nesting limit.
2621 template_arg_pattern = (
2622 r'<[^>]*' # Opening block of <.
2623 r'>([^<]*>)?') # Closing block of >.
2624 # Prefix expressing that whatever follows is not already inside a <...>
2625 # block.
2626 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102627 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552628 not_inside_template_arg_pattern
2629 + r'\bstd::unique_ptr'
2630 + template_arg_pattern
2631 + r'\(\)')
2632
2633 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2634 template_arg_no_array_pattern = (
2635 r'<[^>]*[^]]' # Opening block of <.
2636 r'>([^(<]*[^]]>)?') # Closing block of >.
2637 # Prefix saying that what follows is the start of an expression.
2638 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2639 # Suffix saying that what follows are call parentheses with a non-empty list
2640 # of arguments.
2641 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532642 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552643 return_construct_pattern = input_api.re.compile(
2644 start_of_expr_pattern
2645 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532646 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552647 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532648 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552649 + nonempty_arg_list_pattern)
2650
Vaclav Brozek851d9602018-04-04 16:13:052651 problems_constructor = []
2652 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102653 for f in input_api.AffectedSourceFiles(sources):
2654 for line_number, line in f.ChangedContents():
2655 # Disallow:
2656 # return std::unique_ptr<T>(foo);
2657 # bar = std::unique_ptr<T>(foo);
2658 # But allow:
2659 # return std::unique_ptr<T[]>(foo);
2660 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532661 # And also allow cases when the second template argument is present. Those
2662 # cases cannot be handled by std::make_unique:
2663 # return std::unique_ptr<T, U>(foo);
2664 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052665 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532666 return_construct_result = return_construct_pattern.search(line)
2667 if return_construct_result and not HasMoreThanOneArg(
2668 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052669 problems_constructor.append(
2670 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102671 # Disallow:
2672 # std::unique_ptr<T>()
2673 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052674 problems_nullptr.append(
2675 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2676
2677 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162678 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052679 errors.append(output_api.PresubmitError(
2680 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162681 problems_nullptr))
2682 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052683 errors.append(output_api.PresubmitError(
2684 'The following files use explicit std::unique_ptr constructor.'
2685 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162686 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102687 return errors
2688
2689
[email protected]999261d2014-03-03 20:08:082690def _CheckUserActionUpdate(input_api, output_api):
2691 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522692 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082693 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522694 # If actions.xml is already included in the changelist, the PRESUBMIT
2695 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082696 return []
2697
[email protected]999261d2014-03-03 20:08:082698 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2699 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522700 current_actions = None
[email protected]999261d2014-03-03 20:08:082701 for f in input_api.AffectedFiles(file_filter=file_filter):
2702 for line_num, line in f.ChangedContents():
2703 match = input_api.re.search(action_re, line)
2704 if match:
[email protected]2f92dec2014-03-07 19:21:522705 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2706 # loaded only once.
2707 if not current_actions:
2708 with open('tools/metrics/actions/actions.xml') as actions_f:
2709 current_actions = actions_f.read()
2710 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082711 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522712 action = 'name="{0}"'.format(action_name)
2713 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082714 return [output_api.PresubmitPromptWarning(
2715 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522716 'tools/metrics/actions/actions.xml. Please run '
2717 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082718 % (f.LocalPath(), line_num, action_name))]
2719 return []
2720
2721
Daniel Cheng13ca61a882017-08-25 15:11:252722def _ImportJSONCommentEater(input_api):
2723 import sys
2724 sys.path = sys.path + [input_api.os_path.join(
2725 input_api.PresubmitLocalPath(),
2726 'tools', 'json_comment_eater')]
2727 import json_comment_eater
2728 return json_comment_eater
2729
2730
[email protected]99171a92014-06-03 08:44:472731def _GetJSONParseError(input_api, filename, eat_comments=True):
2732 try:
2733 contents = input_api.ReadFile(filename)
2734 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252735 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132736 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472737
2738 input_api.json.loads(contents)
2739 except ValueError as e:
2740 return e
2741 return None
2742
2743
2744def _GetIDLParseError(input_api, filename):
2745 try:
2746 contents = input_api.ReadFile(filename)
2747 idl_schema = input_api.os_path.join(
2748 input_api.PresubmitLocalPath(),
2749 'tools', 'json_schema_compiler', 'idl_schema.py')
2750 process = input_api.subprocess.Popen(
2751 [input_api.python_executable, idl_schema],
2752 stdin=input_api.subprocess.PIPE,
2753 stdout=input_api.subprocess.PIPE,
2754 stderr=input_api.subprocess.PIPE,
2755 universal_newlines=True)
2756 (_, error) = process.communicate(input=contents)
2757 return error or None
2758 except ValueError as e:
2759 return e
2760
2761
2762def _CheckParseErrors(input_api, output_api):
2763 """Check that IDL and JSON files do not contain syntax errors."""
2764 actions = {
2765 '.idl': _GetIDLParseError,
2766 '.json': _GetJSONParseError,
2767 }
[email protected]99171a92014-06-03 08:44:472768 # Most JSON files are preprocessed and support comments, but these do not.
2769 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042770 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472771 ]
2772 # Only run IDL checker on files in these directories.
2773 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042774 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2775 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472776 ]
2777
2778 def get_action(affected_file):
2779 filename = affected_file.LocalPath()
2780 return actions.get(input_api.os_path.splitext(filename)[1])
2781
[email protected]99171a92014-06-03 08:44:472782 def FilterFile(affected_file):
2783 action = get_action(affected_file)
2784 if not action:
2785 return False
2786 path = affected_file.LocalPath()
2787
Sean Kau46e29bc2017-08-28 16:31:162788 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472789 return False
2790
2791 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162792 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472793 return False
2794 return True
2795
2796 results = []
2797 for affected_file in input_api.AffectedFiles(
2798 file_filter=FilterFile, include_deletes=False):
2799 action = get_action(affected_file)
2800 kwargs = {}
2801 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162802 _MatchesFile(input_api, json_no_comments_patterns,
2803 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472804 kwargs['eat_comments'] = False
2805 parse_error = action(input_api,
2806 affected_file.AbsoluteLocalPath(),
2807 **kwargs)
2808 if parse_error:
2809 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2810 (affected_file.LocalPath(), parse_error)))
2811 return results
2812
2813
[email protected]760deea2013-12-10 19:33:492814def _CheckJavaStyle(input_api, output_api):
2815 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472816 import sys
[email protected]760deea2013-12-10 19:33:492817 original_sys_path = sys.path
2818 try:
2819 sys.path = sys.path + [input_api.os_path.join(
2820 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2821 import checkstyle
2822 finally:
2823 # Restore sys.path to what it was before.
2824 sys.path = original_sys_path
2825
2826 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092827 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512828 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492829
2830
Nate Fischerdfd9812e2019-07-18 22:03:002831def _CheckPythonDevilInit(input_api, output_api):
2832 """Checks to make sure devil is initialized correctly in python scripts."""
2833 script_common_initialize_pattern = input_api.re.compile(
2834 r'script_common\.InitializeEnvironment\(')
2835 devil_env_config_initialize = input_api.re.compile(
2836 r'devil_env\.config\.Initialize\(')
2837
2838 errors = []
2839
2840 sources = lambda affected_file: input_api.FilterSourceFile(
2841 affected_file,
2842 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2843 (r'^build[\\/]android[\\/]devil_chromium\.py',
2844 r'^third_party[\\/].*',)),
2845 white_list=[r'.*\.py$'])
2846
2847 for f in input_api.AffectedSourceFiles(sources):
2848 for line_num, line in f.ChangedContents():
2849 if (script_common_initialize_pattern.search(line) or
2850 devil_env_config_initialize.search(line)):
2851 errors.append("%s:%d" % (f.LocalPath(), line_num))
2852
2853 results = []
2854
2855 if errors:
2856 results.append(output_api.PresubmitError(
2857 'Devil initialization should always be done using '
2858 'devil_chromium.Initialize() in the chromium project, to use better '
2859 'defaults for dependencies (ex. up-to-date version of adb).',
2860 errors))
2861
2862 return results
2863
2864
Sean Kau46e29bc2017-08-28 16:31:162865def _MatchesFile(input_api, patterns, path):
2866 for pattern in patterns:
2867 if input_api.re.search(pattern, path):
2868 return True
2869 return False
2870
2871
Daniel Cheng7052cdf2017-11-21 19:23:292872def _GetOwnersFilesToCheckForIpcOwners(input_api):
2873 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172874
Daniel Cheng7052cdf2017-11-21 19:23:292875 Returns:
2876 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2877 contain to cover IPC-related files with noparent reviewer rules.
2878 """
2879 # Whether or not a file affects IPC is (mostly) determined by a simple list
2880 # of filename patterns.
dchenge07de812016-06-20 19:27:172881 file_patterns = [
palmerb19a0932017-01-24 04:00:312882 # Legacy IPC:
dchenge07de812016-06-20 19:27:172883 '*_messages.cc',
2884 '*_messages*.h',
2885 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312886 # Mojo IPC:
dchenge07de812016-06-20 19:27:172887 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472888 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172889 '*_struct_traits*.*',
2890 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312891 '*.typemap',
2892 # Android native IPC:
2893 '*.aidl',
2894 # Blink uses a different file naming convention:
2895 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472896 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172897 '*StructTraits*.*',
2898 '*TypeConverter*.*',
2899 ]
2900
scottmg7a6ed5ba2016-11-04 18:22:042901 # These third_party directories do not contain IPCs, but contain files
2902 # matching the above patterns, which trigger false positives.
2903 exclude_paths = [
2904 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162905 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232906 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292907 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542908 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162909 # These files are just used to communicate between class loaders running
2910 # in the same process.
2911 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572912 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2913
scottmg7a6ed5ba2016-11-04 18:22:042914 ]
2915
dchenge07de812016-06-20 19:27:172916 # Dictionary mapping an OWNERS file path to Patterns.
2917 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2918 # rules ) to a PatternEntry.
2919 # PatternEntry is a dictionary with two keys:
2920 # - 'files': the files that are matched by this pattern
2921 # - 'rules': the per-file rules needed for this pattern
2922 # For example, if we expect OWNERS file to contain rules for *.mojom and
2923 # *_struct_traits*.*, Patterns might look like this:
2924 # {
2925 # '*.mojom': {
2926 # 'files': ...,
2927 # 'rules': [
2928 # 'per-file *.mojom=set noparent',
2929 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2930 # ],
2931 # },
2932 # '*_struct_traits*.*': {
2933 # 'files': ...,
2934 # 'rules': [
2935 # 'per-file *_struct_traits*.*=set noparent',
2936 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2937 # ],
2938 # },
2939 # }
2940 to_check = {}
2941
Daniel Cheng13ca61a882017-08-25 15:11:252942 def AddPatternToCheck(input_file, pattern):
2943 owners_file = input_api.os_path.join(
2944 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2945 if owners_file not in to_check:
2946 to_check[owners_file] = {}
2947 if pattern not in to_check[owners_file]:
2948 to_check[owners_file][pattern] = {
2949 'files': [],
2950 'rules': [
2951 'per-file %s=set noparent' % pattern,
2952 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2953 ]
2954 }
Vaclav Brozekd5de76a2018-03-17 07:57:502955 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252956
dchenge07de812016-06-20 19:27:172957 # Iterate through the affected files to see what we actually need to check
2958 # for. We should only nag patch authors about per-file rules if a file in that
2959 # directory would match that pattern. If a directory only contains *.mojom
2960 # files and no *_messages*.h files, we should only nag about rules for
2961 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252962 for f in input_api.AffectedFiles(include_deletes=False):
2963 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362964 # affected files for .json, .cc, and .h files which look like they contain
2965 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162966 if (f.LocalPath().endswith('.json') and
2967 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2968 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252969 json_comment_eater = _ImportJSONCommentEater(input_api)
2970 mostly_json_lines = '\n'.join(f.NewContents())
2971 # Comments aren't allowed in strict JSON, so filter them out.
2972 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432973 try:
2974 json_content = input_api.json.loads(json_lines)
2975 except:
2976 # There's another PRESUBMIT check that already verifies that JSON files
2977 # are not invalid, so no need to emit another warning here.
2978 continue
Daniel Cheng13ca61a882017-08-25 15:11:252979 if 'interface_provider_specs' in json_content:
2980 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362981 else:
2982 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2983 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2984 if (manifest_pattern.search(f.LocalPath()) and not
2985 test_manifest_pattern.search(f.LocalPath())):
2986 # We expect all actual service manifest files to contain at least one
2987 # qualified reference to service_manager::Manifest.
2988 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2989 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172990 for pattern in file_patterns:
2991 if input_api.fnmatch.fnmatch(
2992 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042993 skip = False
2994 for exclude in exclude_paths:
2995 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2996 skip = True
2997 break
2998 if skip:
2999 continue
Daniel Cheng13ca61a882017-08-25 15:11:253000 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:173001 break
3002
Daniel Cheng7052cdf2017-11-21 19:23:293003 return to_check
3004
3005
3006def _CheckIpcOwners(input_api, output_api):
3007 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3008 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
3009
3010 if to_check:
3011 # If there are any OWNERS files to check, there are IPC-related changes in
3012 # this CL. Auto-CC the review list.
3013 output_api.AppendCC('[email protected]')
3014
3015 # Go through the OWNERS files to check, filtering out rules that are already
3016 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173017 for owners_file, patterns in to_check.iteritems():
3018 try:
3019 with file(owners_file) as f:
3020 lines = set(f.read().splitlines())
3021 for entry in patterns.itervalues():
3022 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3023 ]
3024 except IOError:
3025 # No OWNERS file, so all the rules are definitely missing.
3026 continue
3027
3028 # All the remaining lines weren't found in OWNERS files, so emit an error.
3029 errors = []
3030 for owners_file, patterns in to_check.iteritems():
3031 missing_lines = []
3032 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503033 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173034 missing_lines.extend(entry['rules'])
3035 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3036 if missing_lines:
3037 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053038 'Because of the presence of files:\n%s\n\n'
3039 '%s needs the following %d lines added:\n\n%s' %
3040 ('\n'.join(files), owners_file, len(missing_lines),
3041 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173042
3043 results = []
3044 if errors:
vabrf5ce3bf92016-07-11 14:52:413045 if input_api.is_committing:
3046 output = output_api.PresubmitError
3047 else:
3048 output = output_api.PresubmitPromptWarning
3049 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593050 'Found OWNERS files that need to be updated for IPC security ' +
3051 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173052 long_text='\n\n'.join(errors)))
3053
3054 return results
3055
3056
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263057def _CheckSetNoParent(input_api, output_api):
3058 """Checks that set noparent is only used together with an OWNERS file in
3059 //build/OWNERS.setnoparent (see also
3060 //docs/code_reviews.md#owners-files-details)
3061 """
3062 errors = []
3063
3064 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3065 allowed_owners_files = set()
3066 with open(allowed_owners_files_file, 'r') as f:
3067 for line in f:
3068 line = line.strip()
3069 if not line or line.startswith('#'):
3070 continue
3071 allowed_owners_files.add(line)
3072
3073 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3074
3075 for f in input_api.AffectedFiles(include_deletes=False):
3076 if not f.LocalPath().endswith('OWNERS'):
3077 continue
3078
3079 found_owners_files = set()
3080 found_set_noparent_lines = dict()
3081
3082 # Parse the OWNERS file.
3083 for lineno, line in enumerate(f.NewContents(), 1):
3084 line = line.strip()
3085 if line.startswith('set noparent'):
3086 found_set_noparent_lines[''] = lineno
3087 if line.startswith('file://'):
3088 if line in allowed_owners_files:
3089 found_owners_files.add('')
3090 if line.startswith('per-file'):
3091 match = per_file_pattern.match(line)
3092 if match:
3093 glob = match.group(1).strip()
3094 directive = match.group(2).strip()
3095 if directive == 'set noparent':
3096 found_set_noparent_lines[glob] = lineno
3097 if directive.startswith('file://'):
3098 if directive in allowed_owners_files:
3099 found_owners_files.add(glob)
3100
3101 # Check that every set noparent line has a corresponding file:// line
3102 # listed in build/OWNERS.setnoparent.
3103 for set_noparent_line in found_set_noparent_lines:
3104 if set_noparent_line in found_owners_files:
3105 continue
3106 errors.append(' %s:%d' % (f.LocalPath(),
3107 found_set_noparent_lines[set_noparent_line]))
3108
3109 results = []
3110 if errors:
3111 if input_api.is_committing:
3112 output = output_api.PresubmitError
3113 else:
3114 output = output_api.PresubmitPromptWarning
3115 results.append(output(
3116 'Found the following "set noparent" restrictions in OWNERS files that '
3117 'do not include owners from build/OWNERS.setnoparent:',
3118 long_text='\n\n'.join(errors)))
3119 return results
3120
3121
jbriance9e12f162016-11-25 07:57:503122def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313123 """Checks that added or removed lines in non third party affected
3124 header files do not lead to new useless class or struct forward
3125 declaration.
jbriance9e12f162016-11-25 07:57:503126 """
3127 results = []
3128 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3129 input_api.re.MULTILINE)
3130 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3131 input_api.re.MULTILINE)
3132 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313133 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193134 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493135 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313136 continue
3137
jbriance9e12f162016-11-25 07:57:503138 if not f.LocalPath().endswith('.h'):
3139 continue
3140
3141 contents = input_api.ReadFile(f)
3142 fwd_decls = input_api.re.findall(class_pattern, contents)
3143 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3144
3145 useless_fwd_decls = []
3146 for decl in fwd_decls:
3147 count = sum(1 for _ in input_api.re.finditer(
3148 r'\b%s\b' % input_api.re.escape(decl), contents))
3149 if count == 1:
3150 useless_fwd_decls.append(decl)
3151
3152 if not useless_fwd_decls:
3153 continue
3154
3155 for line in f.GenerateScmDiff().splitlines():
3156 if (line.startswith('-') and not line.startswith('--') or
3157 line.startswith('+') and not line.startswith('++')):
3158 for decl in useless_fwd_decls:
3159 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3160 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243161 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503162 (f.LocalPath(), decl)))
3163 useless_fwd_decls.remove(decl)
3164
3165 return results
3166
Jinsong Fan91ebbbd2019-04-16 14:57:173167def _CheckAndroidDebuggableBuild(input_api, output_api):
3168 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3169 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3170 this is a debuggable build of Android.
3171 """
3172 build_type_check_pattern = input_api.re.compile(
3173 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3174
3175 errors = []
3176
3177 sources = lambda affected_file: input_api.FilterSourceFile(
3178 affected_file,
3179 black_list=(_EXCLUDED_PATHS +
3180 _TEST_CODE_EXCLUDED_PATHS +
3181 input_api.DEFAULT_BLACK_LIST +
3182 (r"^android_webview[\\/]support_library[\\/]"
3183 "boundary_interfaces[\\/]",
3184 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3185 r'^third_party[\\/].*',
3186 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3187 r"webview[\\/]chromium[\\/]License.*",)),
3188 white_list=[r'.*\.java$'])
3189
3190 for f in input_api.AffectedSourceFiles(sources):
3191 for line_num, line in f.ChangedContents():
3192 if build_type_check_pattern.search(line):
3193 errors.append("%s:%d" % (f.LocalPath(), line_num))
3194
3195 results = []
3196
3197 if errors:
3198 results.append(output_api.PresubmitPromptWarning(
3199 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3200 ' Please use BuildInfo.isDebugAndroid() instead.',
3201 errors))
3202
3203 return results
jbriance9e12f162016-11-25 07:57:503204
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493205# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293206def _CheckAndroidToastUsage(input_api, output_api):
3207 """Checks that code uses org.chromium.ui.widget.Toast instead of
3208 android.widget.Toast (Chromium Toast doesn't force hardware
3209 acceleration on low-end devices, saving memory).
3210 """
3211 toast_import_pattern = input_api.re.compile(
3212 r'^import android\.widget\.Toast;$')
3213
3214 errors = []
3215
3216 sources = lambda affected_file: input_api.FilterSourceFile(
3217 affected_file,
3218 black_list=(_EXCLUDED_PATHS +
3219 _TEST_CODE_EXCLUDED_PATHS +
3220 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043221 (r'^chromecast[\\/].*',
3222 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493223 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293224
3225 for f in input_api.AffectedSourceFiles(sources):
3226 for line_num, line in f.ChangedContents():
3227 if toast_import_pattern.search(line):
3228 errors.append("%s:%d" % (f.LocalPath(), line_num))
3229
3230 results = []
3231
3232 if errors:
3233 results.append(output_api.PresubmitError(
3234 'android.widget.Toast usage is detected. Android toasts use hardware'
3235 ' acceleration, and can be\ncostly on low-end devices. Please use'
3236 ' org.chromium.ui.widget.Toast instead.\n'
3237 'Contact [email protected] if you have any questions.',
3238 errors))
3239
3240 return results
3241
3242
dgnaa68d5e2015-06-10 10:08:223243def _CheckAndroidCrLogUsage(input_api, output_api):
3244 """Checks that new logs using org.chromium.base.Log:
3245 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513246 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223247 """
pkotwicza1dd0b002016-05-16 14:41:043248
torne89540622017-03-24 19:41:303249 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043250 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303251 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043252 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303253 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043254 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3255 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093256 # The customtabs_benchmark is a small app that does not depend on Chromium
3257 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043258 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043259 ]
3260
dgnaa68d5e2015-06-10 10:08:223261 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123262 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3263 class_in_base_pattern = input_api.re.compile(
3264 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3265 has_some_log_import_pattern = input_api.re.compile(
3266 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223267 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123268 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223269 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463270 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223271
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463272 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493273 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043274 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123275
dgnaa68d5e2015-06-10 10:08:223276 tag_decl_errors = []
3277 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123278 tag_errors = []
dgn38736db2015-09-18 19:20:513279 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123280 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223281
3282 for f in input_api.AffectedSourceFiles(sources):
3283 file_content = input_api.ReadFile(f)
3284 has_modified_logs = False
3285
3286 # Per line checks
dgn87d9fb62015-06-12 09:15:123287 if (cr_log_import_pattern.search(file_content) or
3288 (class_in_base_pattern.search(file_content) and
3289 not has_some_log_import_pattern.search(file_content))):
3290 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223291 for line_num, line in f.ChangedContents():
3292
3293 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123294 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223295 if match:
3296 has_modified_logs = True
3297
3298 # Make sure it uses "TAG"
3299 if not match.group('tag') == 'TAG':
3300 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123301 else:
3302 # Report non cr Log function calls in changed lines
3303 for line_num, line in f.ChangedContents():
3304 if log_call_pattern.search(line):
3305 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223306
3307 # Per file checks
3308 if has_modified_logs:
3309 # Make sure the tag is using the "cr" prefix and is not too long
3310 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513311 tag_name = match.group('name') if match else None
3312 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223313 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513314 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223315 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513316 elif '.' in tag_name:
3317 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223318
3319 results = []
3320 if tag_decl_errors:
3321 results.append(output_api.PresubmitPromptWarning(
3322 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513323 '"private static final String TAG = "<package tag>".\n'
3324 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223325 tag_decl_errors))
3326
3327 if tag_length_errors:
3328 results.append(output_api.PresubmitError(
3329 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513330 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223331 tag_length_errors))
3332
3333 if tag_errors:
3334 results.append(output_api.PresubmitPromptWarning(
3335 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3336 tag_errors))
3337
dgn87d9fb62015-06-12 09:15:123338 if util_log_errors:
dgn4401aa52015-04-29 16:26:173339 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123340 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3341 util_log_errors))
3342
dgn38736db2015-09-18 19:20:513343 if tag_with_dot_errors:
3344 results.append(output_api.PresubmitPromptWarning(
3345 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3346 tag_with_dot_errors))
3347
dgn4401aa52015-04-29 16:26:173348 return results
3349
3350
Yoland Yanb92fa522017-08-28 17:37:063351def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3352 """Checks that junit.framework.* is no longer used."""
3353 deprecated_junit_framework_pattern = input_api.re.compile(
3354 r'^import junit\.framework\..*;',
3355 input_api.re.MULTILINE)
3356 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493357 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063358 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133359 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063360 for line_num, line in f.ChangedContents():
3361 if deprecated_junit_framework_pattern.search(line):
3362 errors.append("%s:%d" % (f.LocalPath(), line_num))
3363
3364 results = []
3365 if errors:
3366 results.append(output_api.PresubmitError(
3367 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3368 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3369 ' if you have any question.', errors))
3370 return results
3371
3372
3373def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3374 """Checks that if new Java test classes have inheritance.
3375 Either the new test class is JUnit3 test or it is a JUnit4 test class
3376 with a base class, either case is undesirable.
3377 """
3378 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3379
3380 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493381 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063382 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133383 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063384 if not f.OldContents():
3385 class_declaration_start_flag = False
3386 for line_num, line in f.ChangedContents():
3387 if class_declaration_pattern.search(line):
3388 class_declaration_start_flag = True
3389 if class_declaration_start_flag and ' extends ' in line:
3390 errors.append('%s:%d' % (f.LocalPath(), line_num))
3391 if '{' in line:
3392 class_declaration_start_flag = False
3393
3394 results = []
3395 if errors:
3396 results.append(output_api.PresubmitPromptWarning(
3397 'The newly created files include Test classes that inherits from base'
3398 ' class. Please do not use inheritance in JUnit4 tests or add new'
3399 ' JUnit3 tests. Contact [email protected] if you have any'
3400 ' questions.', errors))
3401 return results
3402
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203403
yolandyan45001472016-12-21 21:12:423404def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3405 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3406 deprecated_annotation_import_pattern = input_api.re.compile(
3407 r'^import android\.test\.suitebuilder\.annotation\..*;',
3408 input_api.re.MULTILINE)
3409 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493410 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423411 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133412 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423413 for line_num, line in f.ChangedContents():
3414 if deprecated_annotation_import_pattern.search(line):
3415 errors.append("%s:%d" % (f.LocalPath(), line_num))
3416
3417 results = []
3418 if errors:
3419 results.append(output_api.PresubmitError(
3420 'Annotations in android.test.suitebuilder.annotation have been'
3421 ' deprecated since API level 24. Please use android.support.test.filters'
3422 ' from //third_party/android_support_test_runner:runner_java instead.'
3423 ' Contact [email protected] if you have any questions.', errors))
3424 return results
3425
3426
agrieve7b6479d82015-10-07 14:24:223427def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3428 """Checks if MDPI assets are placed in a correct directory."""
3429 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3430 ('/res/drawable/' in f.LocalPath() or
3431 '/res/drawable-ldrtl/' in f.LocalPath()))
3432 errors = []
3433 for f in input_api.AffectedFiles(include_deletes=False,
3434 file_filter=file_filter):
3435 errors.append(' %s' % f.LocalPath())
3436
3437 results = []
3438 if errors:
3439 results.append(output_api.PresubmitError(
3440 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3441 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3442 '/res/drawable-ldrtl/.\n'
3443 'Contact [email protected] if you have questions.', errors))
3444 return results
3445
3446
Nate Fischer535972b2017-09-16 01:06:183447def _CheckAndroidWebkitImports(input_api, output_api):
3448 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353449 android.webview.ValueCallback except in the WebView glue layer
3450 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183451 """
3452 valuecallback_import_pattern = input_api.re.compile(
3453 r'^import android\.webkit\.ValueCallback;$')
3454
3455 errors = []
3456
3457 sources = lambda affected_file: input_api.FilterSourceFile(
3458 affected_file,
3459 black_list=(_EXCLUDED_PATHS +
3460 _TEST_CODE_EXCLUDED_PATHS +
3461 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353462 (r'^android_webview[\\/]glue[\\/].*',
3463 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493464 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183465
3466 for f in input_api.AffectedSourceFiles(sources):
3467 for line_num, line in f.ChangedContents():
3468 if valuecallback_import_pattern.search(line):
3469 errors.append("%s:%d" % (f.LocalPath(), line_num))
3470
3471 results = []
3472
3473 if errors:
3474 results.append(output_api.PresubmitError(
3475 'android.webkit.ValueCallback usage is detected outside of the glue'
3476 ' layer. To stay compatible with the support library, android.webkit.*'
3477 ' classes should only be used inside the glue layer and'
3478 ' org.chromium.base.Callback should be used instead.',
3479 errors))
3480
3481 return results
3482
3483
Becky Zhou7c69b50992018-12-10 19:37:573484def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3485 """Checks Android XML styles """
3486 import sys
3487 original_sys_path = sys.path
3488 try:
3489 sys.path = sys.path + [input_api.os_path.join(
3490 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3491 import checkxmlstyle
3492 finally:
3493 # Restore sys.path to what it was before.
3494 sys.path = original_sys_path
3495
3496 if is_check_on_upload:
3497 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3498 else:
3499 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3500
3501
agrievef32bcc72016-04-04 14:57:403502class PydepsChecker(object):
3503 def __init__(self, input_api, pydeps_files):
3504 self._file_cache = {}
3505 self._input_api = input_api
3506 self._pydeps_files = pydeps_files
3507
3508 def _LoadFile(self, path):
3509 """Returns the list of paths within a .pydeps file relative to //."""
3510 if path not in self._file_cache:
3511 with open(path) as f:
3512 self._file_cache[path] = f.read()
3513 return self._file_cache[path]
3514
3515 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3516 """Returns an interable of paths within the .pydep, relativized to //."""
3517 os_path = self._input_api.os_path
3518 pydeps_dir = os_path.dirname(pydeps_path)
3519 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3520 if not l.startswith('*'))
3521 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3522
3523 def _CreateFilesToPydepsMap(self):
3524 """Returns a map of local_path -> list_of_pydeps."""
3525 ret = {}
3526 for pydep_local_path in self._pydeps_files:
3527 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3528 ret.setdefault(path, []).append(pydep_local_path)
3529 return ret
3530
3531 def ComputeAffectedPydeps(self):
3532 """Returns an iterable of .pydeps files that might need regenerating."""
3533 affected_pydeps = set()
3534 file_to_pydeps_map = None
3535 for f in self._input_api.AffectedFiles(include_deletes=True):
3536 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463537 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3538 # subrepositories. We can't figure out which files change, so re-check
3539 # all files.
3540 # Changes to print_python_deps.py affect all .pydeps.
3541 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403542 return self._pydeps_files
3543 elif local_path.endswith('.pydeps'):
3544 if local_path in self._pydeps_files:
3545 affected_pydeps.add(local_path)
3546 elif local_path.endswith('.py'):
3547 if file_to_pydeps_map is None:
3548 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3549 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3550 return affected_pydeps
3551
3552 def DetermineIfStale(self, pydeps_path):
3553 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413554 import difflib
John Budorick47ca3fe2018-02-10 00:53:103555 import os
3556
agrievef32bcc72016-04-04 14:57:403557 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3558 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103559 env = dict(os.environ)
3560 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403561 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103562 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413563 old_contents = old_pydeps_data[2:]
3564 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403565 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413566 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403567
3568
Tibor Goldschwendt360793f72019-06-25 18:23:493569def _ParseGclientArgs():
3570 args = {}
3571 with open('build/config/gclient_args.gni', 'r') as f:
3572 for line in f:
3573 line = line.strip()
3574 if not line or line.startswith('#'):
3575 continue
3576 attribute, value = line.split('=')
3577 args[attribute.strip()] = value.strip()
3578 return args
3579
3580
agrievef32bcc72016-04-04 14:57:403581def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3582 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403583 # This check is for Python dependency lists (.pydeps files), and involves
3584 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3585 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283586 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003587 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493588 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403589 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3590 results = []
3591 # First, check for new / deleted .pydeps.
3592 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033593 # Check whether we are running the presubmit check for a file in src.
3594 # f.LocalPath is relative to repo (src, or internal repo).
3595 # os_path.exists is relative to src repo.
3596 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3597 # to src and we can conclude that the pydeps is in src.
3598 if input_api.os_path.exists(f.LocalPath()):
3599 if f.LocalPath().endswith('.pydeps'):
3600 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3601 results.append(output_api.PresubmitError(
3602 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3603 'remove %s' % f.LocalPath()))
3604 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3605 results.append(output_api.PresubmitError(
3606 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3607 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403608
3609 if results:
3610 return results
3611
3612 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3613
3614 for pydep_path in checker.ComputeAffectedPydeps():
3615 try:
phajdan.jr0d9878552016-11-04 10:49:413616 result = checker.DetermineIfStale(pydep_path)
3617 if result:
3618 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403619 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413620 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3621 'To regenerate, run:\n\n %s' %
3622 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403623 except input_api.subprocess.CalledProcessError as error:
3624 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3625 long_text=error.output)]
3626
3627 return results
3628
3629
glidere61efad2015-02-18 17:39:433630def _CheckSingletonInHeaders(input_api, output_api):
3631 """Checks to make sure no header files have |Singleton<|."""
3632 def FileFilter(affected_file):
3633 # It's ok for base/memory/singleton.h to have |Singleton<|.
3634 black_list = (_EXCLUDED_PATHS +
3635 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043636 (r"^base[\\/]memory[\\/]singleton\.h$",
3637 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473638 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433639 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3640
sergeyu34d21222015-09-16 00:11:443641 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433642 files = []
3643 for f in input_api.AffectedSourceFiles(FileFilter):
3644 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3645 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3646 contents = input_api.ReadFile(f)
3647 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243648 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433649 pattern.search(line)):
3650 files.append(f)
3651 break
3652
3653 if files:
yolandyandaabc6d2016-04-18 18:29:393654 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443655 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433656 'Please move them to an appropriate source file so that the ' +
3657 'template gets instantiated in a single compilation unit.',
3658 files) ]
3659 return []
3660
3661
[email protected]fd20b902014-05-09 02:14:533662_DEPRECATED_CSS = [
3663 # Values
3664 ( "-webkit-box", "flex" ),
3665 ( "-webkit-inline-box", "inline-flex" ),
3666 ( "-webkit-flex", "flex" ),
3667 ( "-webkit-inline-flex", "inline-flex" ),
3668 ( "-webkit-min-content", "min-content" ),
3669 ( "-webkit-max-content", "max-content" ),
3670
3671 # Properties
3672 ( "-webkit-background-clip", "background-clip" ),
3673 ( "-webkit-background-origin", "background-origin" ),
3674 ( "-webkit-background-size", "background-size" ),
3675 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443676 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533677
3678 # Functions
3679 ( "-webkit-gradient", "gradient" ),
3680 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3681 ( "-webkit-linear-gradient", "linear-gradient" ),
3682 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3683 ( "-webkit-radial-gradient", "radial-gradient" ),
3684 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3685]
3686
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203687
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493688# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243689def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533690 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253691 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343692 documentation and iOS CSS for dom distiller
3693 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253694 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533695 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493696 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253697 black_list = (_EXCLUDED_PATHS +
3698 _TEST_CODE_EXCLUDED_PATHS +
3699 input_api.DEFAULT_BLACK_LIST +
3700 (r"^chrome/common/extensions/docs",
3701 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343702 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443703 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253704 r"^native_client_sdk"))
3705 file_filter = lambda f: input_api.FilterSourceFile(
3706 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533707 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3708 for line_num, line in fpath.ChangedContents():
3709 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023710 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533711 results.append(output_api.PresubmitError(
3712 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3713 (fpath.LocalPath(), line_num, deprecated_value, value)))
3714 return results
3715
mohan.reddyf21db962014-10-16 12:26:473716
rlanday6802cf632017-05-30 17:48:363717def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363718 bad_files = {}
3719 for f in input_api.AffectedFiles(include_deletes=False):
3720 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493721 not f.LocalPath().startswith('third_party/blink') and
3722 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363723 continue
3724
Daniel Bratell65b033262019-04-23 08:17:063725 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363726 continue
3727
Vaclav Brozekd5de76a2018-03-17 07:57:503728 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363729 if "#include" in line and "../" in line]
3730 if not relative_includes:
3731 continue
3732 bad_files[f.LocalPath()] = relative_includes
3733
3734 if not bad_files:
3735 return []
3736
3737 error_descriptions = []
3738 for file_path, bad_lines in bad_files.iteritems():
3739 error_description = file_path
3740 for line in bad_lines:
3741 error_description += '\n ' + line
3742 error_descriptions.append(error_description)
3743
3744 results = []
3745 results.append(output_api.PresubmitError(
3746 'You added one or more relative #include paths (including "../").\n'
3747 'These shouldn\'t be used because they can be used to include headers\n'
3748 'from code that\'s not correctly specified as a dependency in the\n'
3749 'relevant BUILD.gn file(s).',
3750 error_descriptions))
3751
3752 return results
3753
Takeshi Yoshinoe387aa32017-08-02 13:16:133754
Daniel Bratell65b033262019-04-23 08:17:063755def _CheckForCcIncludes(input_api, output_api):
3756 """Check that nobody tries to include a cc file. It's a relatively
3757 common error which results in duplicate symbols in object
3758 files. This may not always break the build until someone later gets
3759 very confusing linking errors."""
3760 results = []
3761 for f in input_api.AffectedFiles(include_deletes=False):
3762 # We let third_party code do whatever it wants
3763 if (f.LocalPath().startswith('third_party') and
3764 not f.LocalPath().startswith('third_party/blink') and
3765 not f.LocalPath().startswith('third_party\\blink')):
3766 continue
3767
3768 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3769 continue
3770
3771 for _, line in f.ChangedContents():
3772 if line.startswith('#include "'):
3773 included_file = line.split('"')[1]
3774 if _IsCPlusPlusFile(input_api, included_file):
3775 # The most common naming for external files with C++ code,
3776 # apart from standard headers, is to call them foo.inc, but
3777 # Chromium sometimes uses foo-inc.cc so allow that as well.
3778 if not included_file.endswith(('.h', '-inc.cc')):
3779 results.append(output_api.PresubmitError(
3780 'Only header files or .inc files should be included in other\n'
3781 'C++ files. Compiling the contents of a cc file more than once\n'
3782 'will cause duplicate information in the build which may later\n'
3783 'result in strange link_errors.\n' +
3784 f.LocalPath() + ':\n ' +
3785 line))
3786
3787 return results
3788
3789
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203790def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3791 if not isinstance(key, ast.Str):
3792 return 'Key at line %d must be a string literal' % key.lineno
3793 if not isinstance(value, ast.Dict):
3794 return 'Value at line %d must be a dict' % value.lineno
3795 if len(value.keys) != 1:
3796 return 'Dict at line %d must have single entry' % value.lineno
3797 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3798 return (
3799 'Entry at line %d must have a string literal \'filepath\' as key' %
3800 value.lineno)
3801 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133802
Takeshi Yoshinoe387aa32017-08-02 13:16:133803
Sergey Ulanov4af16052018-11-08 02:41:463804def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203805 if not isinstance(key, ast.Str):
3806 return 'Key at line %d must be a string literal' % key.lineno
3807 if not isinstance(value, ast.List):
3808 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463809 for element in value.elts:
3810 if not isinstance(element, ast.Str):
3811 return 'Watchlist elements on line %d is not a string' % key.lineno
3812 if not email_regex.match(element.s):
3813 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3814 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203815 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133816
Takeshi Yoshinoe387aa32017-08-02 13:16:133817
Sergey Ulanov4af16052018-11-08 02:41:463818def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203819 mismatch_template = (
3820 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3821 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133822
Sergey Ulanov4af16052018-11-08 02:41:463823 email_regex = input_api.re.compile(
3824 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3825
3826 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203827 i = 0
3828 last_key = ''
3829 while True:
3830 if i >= len(wd_dict.keys):
3831 if i >= len(w_dict.keys):
3832 return None
3833 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3834 elif i >= len(w_dict.keys):
3835 return (
3836 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133837
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203838 wd_key = wd_dict.keys[i]
3839 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133840
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203841 result = _CheckWatchlistDefinitionsEntrySyntax(
3842 wd_key, wd_dict.values[i], ast)
3843 if result is not None:
3844 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133845
Sergey Ulanov4af16052018-11-08 02:41:463846 result = _CheckWatchlistsEntrySyntax(
3847 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203848 if result is not None:
3849 return 'Bad entry in WATCHLISTS dict: %s' % result
3850
3851 if wd_key.s != w_key.s:
3852 return mismatch_template % (
3853 '%s at line %d' % (wd_key.s, wd_key.lineno),
3854 '%s at line %d' % (w_key.s, w_key.lineno))
3855
3856 if wd_key.s < last_key:
3857 return (
3858 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3859 (wd_key.lineno, w_key.lineno))
3860 last_key = wd_key.s
3861
3862 i = i + 1
3863
3864
Sergey Ulanov4af16052018-11-08 02:41:463865def _CheckWATCHLISTSSyntax(expression, input_api):
3866 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203867 if not isinstance(expression, ast.Expression):
3868 return 'WATCHLISTS file must contain a valid expression'
3869 dictionary = expression.body
3870 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3871 return 'WATCHLISTS file must have single dict with exactly two entries'
3872
3873 first_key = dictionary.keys[0]
3874 first_value = dictionary.values[0]
3875 second_key = dictionary.keys[1]
3876 second_value = dictionary.values[1]
3877
3878 if (not isinstance(first_key, ast.Str) or
3879 first_key.s != 'WATCHLIST_DEFINITIONS' or
3880 not isinstance(first_value, ast.Dict)):
3881 return (
3882 'The first entry of the dict in WATCHLISTS file must be '
3883 'WATCHLIST_DEFINITIONS dict')
3884
3885 if (not isinstance(second_key, ast.Str) or
3886 second_key.s != 'WATCHLISTS' or
3887 not isinstance(second_value, ast.Dict)):
3888 return (
3889 'The second entry of the dict in WATCHLISTS file must be '
3890 'WATCHLISTS dict')
3891
Sergey Ulanov4af16052018-11-08 02:41:463892 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133893
3894
3895def _CheckWATCHLISTS(input_api, output_api):
3896 for f in input_api.AffectedFiles(include_deletes=False):
3897 if f.LocalPath() == 'WATCHLISTS':
3898 contents = input_api.ReadFile(f, 'r')
3899
3900 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203901 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133902 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203903 # Get an AST tree for it and scan the tree for detailed style checking.
3904 expression = input_api.ast.parse(
3905 contents, filename='WATCHLISTS', mode='eval')
3906 except ValueError as e:
3907 return [output_api.PresubmitError(
3908 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3909 except SyntaxError as e:
3910 return [output_api.PresubmitError(
3911 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3912 except TypeError as e:
3913 return [output_api.PresubmitError(
3914 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133915
Sergey Ulanov4af16052018-11-08 02:41:463916 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203917 if result is not None:
3918 return [output_api.PresubmitError(result)]
3919 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133920
3921 return []
3922
3923
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193924def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3925 """Checks that newly added header files have corresponding GN changes.
3926 Note that this is only a heuristic. To be precise, run script:
3927 build/check_gn_headers.py.
3928 """
3929
3930 def headers(f):
3931 return input_api.FilterSourceFile(
3932 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3933
3934 new_headers = []
3935 for f in input_api.AffectedSourceFiles(headers):
3936 if f.Action() != 'A':
3937 continue
3938 new_headers.append(f.LocalPath())
3939
3940 def gn_files(f):
3941 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3942
3943 all_gn_changed_contents = ''
3944 for f in input_api.AffectedSourceFiles(gn_files):
3945 for _, line in f.ChangedContents():
3946 all_gn_changed_contents += line
3947
3948 problems = []
3949 for header in new_headers:
3950 basename = input_api.os_path.basename(header)
3951 if basename not in all_gn_changed_contents:
3952 problems.append(header)
3953
3954 if problems:
3955 return [output_api.PresubmitPromptWarning(
3956 'Missing GN changes for new header files', items=sorted(problems),
3957 long_text='Please double check whether newly added header files need '
3958 'corresponding changes in gn or gni files.\nThis checking is only a '
3959 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3960 'Read https://crbug.com/661774 for more info.')]
3961 return []
3962
3963
Michael Giuffridad3bc8672018-10-25 22:48:023964def _CheckCorrectProductNameInMessages(input_api, output_api):
3965 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3966
3967 This assumes we won't intentionally reference one product from the other
3968 product.
3969 """
3970 all_problems = []
3971 test_cases = [{
3972 "filename_postfix": "google_chrome_strings.grd",
3973 "correct_name": "Chrome",
3974 "incorrect_name": "Chromium",
3975 }, {
3976 "filename_postfix": "chromium_strings.grd",
3977 "correct_name": "Chromium",
3978 "incorrect_name": "Chrome",
3979 }]
3980
3981 for test_case in test_cases:
3982 problems = []
3983 filename_filter = lambda x: x.LocalPath().endswith(
3984 test_case["filename_postfix"])
3985
3986 # Check each new line. Can yield false positives in multiline comments, but
3987 # easier than trying to parse the XML because messages can have nested
3988 # children, and associating message elements with affected lines is hard.
3989 for f in input_api.AffectedSourceFiles(filename_filter):
3990 for line_num, line in f.ChangedContents():
3991 if "<message" in line or "<!--" in line or "-->" in line:
3992 continue
3993 if test_case["incorrect_name"] in line:
3994 problems.append(
3995 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3996
3997 if problems:
3998 message = (
3999 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
4000 % (test_case["correct_name"], test_case["correct_name"],
4001 test_case["incorrect_name"]))
4002 all_problems.append(
4003 output_api.PresubmitPromptWarning(message, items=problems))
4004
4005 return all_problems
4006
4007
Dirk Pranke3c18a382019-03-15 01:07:514008def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4009 # TODO(crbug.com/941824): We need to make sure the entries in
4010 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4011 # so that users of //buildtools in other projects get the same tooling
4012 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4013 # support to gclient, we can eliminate the duplication and delete
4014 # this presubmit check.
4015
4016 # Update this regexp if new revisions are added to the files.
4017 rev_regexp = input_api.re.compile(
Xiaohui Chen3fdc6742020-02-29 02:13:264018 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:514019
4020 # If a user is changing one revision, they need to change the same
4021 # line in both files. This means that any given change should contain
4022 # exactly the same list of changed lines that match the regexps. The
4023 # replace(' ', '') call allows us to ignore whitespace changes to the
4024 # lines. The 'long_text' parameter to the error will contain the
4025 # list of changed lines in both files, which should make it easy enough
4026 # to spot the error without going overboard in this implementation.
4027 revs_changes = {
4028 'DEPS': {},
4029 'buildtools/DEPS': {},
4030 }
4031 long_text = ''
4032
4033 for f in input_api.AffectedFiles(
4034 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4035 for line_num, line in f.ChangedContents():
4036 if rev_regexp.search(line):
4037 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4038 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4039
4040 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4041 return [output_api.PresubmitError(
4042 'Change buildtools revisions in sync in both //DEPS and '
4043 '//buildtools/DEPS.', long_text=long_text + '\n')]
4044 else:
4045 return []
4046
4047
Daniel Bratell93eb6c62019-04-29 20:13:364048def _CheckForTooLargeFiles(input_api, output_api):
4049 """Avoid large files, especially binary files, in the repository since
4050 git doesn't scale well for those. They will be in everyone's repo
4051 clones forever, forever making Chromium slower to clone and work
4052 with."""
4053
4054 # Uploading files to cloud storage is not trivial so we don't want
4055 # to set the limit too low, but the upper limit for "normal" large
4056 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4057 # anything over 20 MB is exceptional.
4058 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4059
4060 too_large_files = []
4061 for f in input_api.AffectedFiles():
4062 # Check both added and modified files (but not deleted files).
4063 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384064 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364065 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4066 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4067
4068 if too_large_files:
4069 message = (
4070 'Do not commit large files to git since git scales badly for those.\n' +
4071 'Instead put the large files in cloud storage and use DEPS to\n' +
4072 'fetch them.\n' + '\n'.join(too_large_files)
4073 )
4074 return [output_api.PresubmitError(
4075 'Too large files found in commit', long_text=message + '\n')]
4076 else:
4077 return []
4078
Max Morozb47503b2019-08-08 21:03:274079
4080def _CheckFuzzTargets(input_api, output_api):
4081 """Checks specific for fuzz target sources."""
4082 EXPORTED_SYMBOLS = [
4083 'LLVMFuzzerInitialize',
4084 'LLVMFuzzerCustomMutator',
4085 'LLVMFuzzerCustomCrossOver',
4086 'LLVMFuzzerMutate',
4087 ]
4088
4089 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4090
4091 def FilterFile(affected_file):
4092 """Ignore libFuzzer source code."""
4093 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4094 black_list = r"^third_party[\\/]libFuzzer"
4095
4096 return input_api.FilterSourceFile(
4097 affected_file,
4098 white_list=[white_list],
4099 black_list=[black_list])
4100
4101 files_with_missing_header = []
4102 for f in input_api.AffectedSourceFiles(FilterFile):
4103 contents = input_api.ReadFile(f, 'r')
4104 if REQUIRED_HEADER in contents:
4105 continue
4106
4107 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4108 files_with_missing_header.append(f.LocalPath())
4109
4110 if not files_with_missing_header:
4111 return []
4112
4113 long_text = (
4114 'If you define any of the libFuzzer optional functions (%s), it is '
4115 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4116 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4117 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4118 'to access command line arguments passed to the fuzzer. Instead, prefer '
4119 'static initialization and shared resources as documented in '
4120 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4121 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4122 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4123 )
4124
4125 return [output_api.PresubmitPromptWarning(
4126 message="Missing '%s' in:" % REQUIRED_HEADER,
4127 items=files_with_missing_header,
4128 long_text=long_text)]
4129
4130
Mohamed Heikald048240a2019-11-12 16:57:374131def _CheckNewImagesWarning(input_api, output_api):
4132 """
4133 Warns authors who add images into the repo to make sure their images are
4134 optimized before committing.
4135 """
4136 images_added = False
4137 image_paths = []
4138 errors = []
4139 filter_lambda = lambda x: input_api.FilterSourceFile(
4140 x,
4141 black_list=(('(?i).*test', r'.*\/junit\/')
4142 + input_api.DEFAULT_BLACK_LIST),
4143 white_list=[r'.*\/(drawable|mipmap)' ]
4144 )
4145 for f in input_api.AffectedFiles(
4146 include_deletes=False, file_filter=filter_lambda):
4147 local_path = f.LocalPath().lower()
4148 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4149 images_added = True
4150 image_paths.append(f)
4151 if images_added:
4152 errors.append(output_api.PresubmitPromptWarning(
4153 'It looks like you are trying to commit some images. If these are '
4154 'non-test-only images, please make sure to read and apply the tips in '
4155 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4156 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4157 'FYI only and will not block your CL on the CQ.', image_paths))
4158 return errors
4159
4160
dgnaa68d5e2015-06-10 10:08:224161def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574162 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224163 results = []
dgnaa68d5e2015-06-10 10:08:224164 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174165 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224166 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294167 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064168 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4169 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424170 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184171 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574172 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374173 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154174 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574175 return results
4176
4177def _AndroidSpecificOnCommitChecks(input_api, output_api):
4178 """Groups commit checks that target android code."""
4179 results = []
4180 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224181 return results
4182
4183
[email protected]22c9bd72011-03-27 16:47:394184def _CommonChecks(input_api, output_api):
4185 """Checks common to both upload and commit."""
4186 results = []
4187 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384188 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544189 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084190
4191 author = input_api.change.author_email
4192 if author and author not in _KNOWN_ROBOTS:
4193 results.extend(
4194 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4195
[email protected]55459852011-08-10 15:17:194196 results.extend(
[email protected]760deea2013-12-10 19:33:494197 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234198 results.extend(
4199 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544200 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184201 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344202 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524203 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224204 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444205 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594206 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314207 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064208 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124209 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184210 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224211 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304212 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494213 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034214 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494215 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444216 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294217 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274218 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074219 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544220 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444221 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394222 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554223 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044224 results.extend(
4225 input_api.canned_checks.CheckChangeHasNoTabs(
4226 input_api,
4227 output_api,
4228 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404229 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164230 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084231 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244232 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474233 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044234 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054235 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144236 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234237 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434238 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404239 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154240 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174241 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264242 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504243 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364244 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064245 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134246 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434247 results.extend(input_api.RunTests(
4248 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144249 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024250 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514251 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364252 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004253 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244254
Vaclav Brozekcdc7defb2018-03-20 09:54:354255 for f in input_api.AffectedFiles():
4256 path, name = input_api.os_path.split(f.LocalPath())
4257 if name == 'PRESUBMIT.py':
4258 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004259 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4260 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074261 # The PRESUBMIT.py file (and the directory containing it) might
4262 # have been affected by being moved or removed, so only try to
4263 # run the tests if they still exist.
4264 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4265 input_api, output_api, full_path,
4266 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394267 return results
[email protected]1f7b4172010-01-28 01:17:344268
[email protected]b337cb5b2011-01-23 21:24:054269
[email protected]b8079ae4a2012-12-05 19:56:494270def _CheckPatchFiles(input_api, output_api):
4271 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4272 if f.LocalPath().endswith(('.orig', '.rej'))]
4273 if problems:
4274 return [output_api.PresubmitError(
4275 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034276 else:
4277 return []
[email protected]b8079ae4a2012-12-05 19:56:494278
4279
Kent Tamura5a8755d2017-06-29 23:37:074280def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214281 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4282 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4283 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074284 include_re = input_api.re.compile(
4285 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4286 extension_re = input_api.re.compile(r'\.[a-z]+$')
4287 errors = []
4288 for f in input_api.AffectedFiles():
4289 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4290 continue
4291 found_line_number = None
4292 found_macro = None
4293 for line_num, line in f.ChangedContents():
4294 match = macro_re.search(line)
4295 if match:
4296 found_line_number = line_num
4297 found_macro = match.group(2)
4298 break
4299 if not found_line_number:
4300 continue
4301
4302 found_include = False
4303 for line in f.NewContents():
4304 if include_re.search(line):
4305 found_include = True
4306 break
4307 if found_include:
4308 continue
4309
4310 if not f.LocalPath().endswith('.h'):
4311 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4312 try:
4313 content = input_api.ReadFile(primary_header_path, 'r')
4314 if include_re.search(content):
4315 continue
4316 except IOError:
4317 pass
4318 errors.append('%s:%d %s macro is used without including build/'
4319 'build_config.h.'
4320 % (f.LocalPath(), found_line_number, found_macro))
4321 if errors:
4322 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4323 return []
4324
4325
[email protected]b00342e7f2013-03-26 16:21:544326def _DidYouMeanOSMacro(bad_macro):
4327 try:
4328 return {'A': 'OS_ANDROID',
4329 'B': 'OS_BSD',
4330 'C': 'OS_CHROMEOS',
4331 'F': 'OS_FREEBSD',
4332 'L': 'OS_LINUX',
4333 'M': 'OS_MACOSX',
4334 'N': 'OS_NACL',
4335 'O': 'OS_OPENBSD',
4336 'P': 'OS_POSIX',
4337 'S': 'OS_SOLARIS',
4338 'W': 'OS_WIN'}[bad_macro[3].upper()]
4339 except KeyError:
4340 return ''
4341
4342
4343def _CheckForInvalidOSMacrosInFile(input_api, f):
4344 """Check for sensible looking, totally invalid OS macros."""
4345 preprocessor_statement = input_api.re.compile(r'^\s*#')
4346 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4347 results = []
4348 for lnum, line in f.ChangedContents():
4349 if preprocessor_statement.search(line):
4350 for match in os_macro.finditer(line):
4351 if not match.group(1) in _VALID_OS_MACROS:
4352 good = _DidYouMeanOSMacro(match.group(1))
4353 did_you_mean = ' (did you mean %s?)' % good if good else ''
4354 results.append(' %s:%d %s%s' % (f.LocalPath(),
4355 lnum,
4356 match.group(1),
4357 did_you_mean))
4358 return results
4359
4360
4361def _CheckForInvalidOSMacros(input_api, output_api):
4362 """Check all affected files for invalid OS macros."""
4363 bad_macros = []
tzik3f295992018-12-04 20:32:234364 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474365 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544366 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4367
4368 if not bad_macros:
4369 return []
4370
4371 return [output_api.PresubmitError(
4372 'Possibly invalid OS macro[s] found. Please fix your code\n'
4373 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4374
lliabraa35bab3932014-10-01 12:16:444375
4376def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4377 """Check all affected files for invalid "if defined" macros."""
4378 ALWAYS_DEFINED_MACROS = (
4379 "TARGET_CPU_PPC",
4380 "TARGET_CPU_PPC64",
4381 "TARGET_CPU_68K",
4382 "TARGET_CPU_X86",
4383 "TARGET_CPU_ARM",
4384 "TARGET_CPU_MIPS",
4385 "TARGET_CPU_SPARC",
4386 "TARGET_CPU_ALPHA",
4387 "TARGET_IPHONE_SIMULATOR",
4388 "TARGET_OS_EMBEDDED",
4389 "TARGET_OS_IPHONE",
4390 "TARGET_OS_MAC",
4391 "TARGET_OS_UNIX",
4392 "TARGET_OS_WIN32",
4393 )
4394 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4395 results = []
4396 for lnum, line in f.ChangedContents():
4397 for match in ifdef_macro.finditer(line):
4398 if match.group(1) in ALWAYS_DEFINED_MACROS:
4399 always_defined = ' %s is always defined. ' % match.group(1)
4400 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4401 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4402 lnum,
4403 always_defined,
4404 did_you_mean))
4405 return results
4406
4407
4408def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4409 """Check all affected files for invalid "if defined" macros."""
4410 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054411 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444412 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054413 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214414 continue
lliabraa35bab3932014-10-01 12:16:444415 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4416 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4417
4418 if not bad_macros:
4419 return []
4420
4421 return [output_api.PresubmitError(
4422 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4423 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4424 bad_macros)]
4425
4426
mlamouria82272622014-09-16 18:45:044427def _CheckForIPCRules(input_api, output_api):
4428 """Check for same IPC rules described in
4429 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4430 """
4431 base_pattern = r'IPC_ENUM_TRAITS\('
4432 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4433 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4434
4435 problems = []
4436 for f in input_api.AffectedSourceFiles(None):
4437 local_path = f.LocalPath()
4438 if not local_path.endswith('.h'):
4439 continue
4440 for line_number, line in f.ChangedContents():
4441 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4442 problems.append(
4443 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4444
4445 if problems:
4446 return [output_api.PresubmitPromptWarning(
4447 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4448 else:
4449 return []
4450
[email protected]b00342e7f2013-03-26 16:21:544451
Stephen Martinis97a394142018-06-07 23:06:054452def _CheckForLongPathnames(input_api, output_api):
4453 """Check to make sure no files being submitted have long paths.
4454 This causes issues on Windows.
4455 """
4456 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194457 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054458 local_path = f.LocalPath()
4459 # Windows has a path limit of 260 characters. Limit path length to 200 so
4460 # that we have some extra for the prefix on dev machines and the bots.
4461 if len(local_path) > 200:
4462 problems.append(local_path)
4463
4464 if problems:
4465 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4466 else:
4467 return []
4468
4469
Daniel Bratell8ba52722018-03-02 16:06:144470def _CheckForIncludeGuards(input_api, output_api):
4471 """Check that header files have proper guards against multiple inclusion.
4472 If a file should not have such guards (and it probably should) then it
4473 should include the string "no-include-guard-because-multiply-included".
4474 """
Daniel Bratell6a75baef62018-06-04 10:04:454475 def is_chromium_header_file(f):
4476 # We only check header files under the control of the Chromium
4477 # project. That is, those outside third_party apart from
4478 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324479 # We also exclude *_message_generator.h headers as they use
4480 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454481 file_with_path = input_api.os_path.normpath(f.LocalPath())
4482 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324483 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454484 (not file_with_path.startswith('third_party') or
4485 file_with_path.startswith(
4486 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144487
4488 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344489 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144490
4491 errors = []
4492
Daniel Bratell6a75baef62018-06-04 10:04:454493 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144494 guard_name = None
4495 guard_line_number = None
4496 seen_guard_end = False
4497
4498 file_with_path = input_api.os_path.normpath(f.LocalPath())
4499 base_file_name = input_api.os_path.splitext(
4500 input_api.os_path.basename(file_with_path))[0]
4501 upper_base_file_name = base_file_name.upper()
4502
4503 expected_guard = replace_special_with_underscore(
4504 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144505
4506 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574507 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4508 # are too many (1000+) files with slight deviations from the
4509 # coding style. The most important part is that the include guard
4510 # is there, and that it's unique, not the name so this check is
4511 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144512 #
4513 # As code becomes more uniform, this could be made stricter.
4514
4515 guard_name_pattern_list = [
4516 # Anything with the right suffix (maybe with an extra _).
4517 r'\w+_H__?',
4518
Daniel Bratell39b5b062018-05-16 18:09:574519 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144520 r'\w+_h',
4521
4522 # Anything including the uppercase name of the file.
4523 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4524 upper_base_file_name)) + r'\w*',
4525 ]
4526 guard_name_pattern = '|'.join(guard_name_pattern_list)
4527 guard_pattern = input_api.re.compile(
4528 r'#ifndef\s+(' + guard_name_pattern + ')')
4529
4530 for line_number, line in enumerate(f.NewContents()):
4531 if 'no-include-guard-because-multiply-included' in line:
4532 guard_name = 'DUMMY' # To not trigger check outside the loop.
4533 break
4534
4535 if guard_name is None:
4536 match = guard_pattern.match(line)
4537 if match:
4538 guard_name = match.group(1)
4539 guard_line_number = line_number
4540
Daniel Bratell39b5b062018-05-16 18:09:574541 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454542 # don't match the chromium style guide, but new files should
4543 # get it right.
4544 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574545 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144546 errors.append(output_api.PresubmitPromptWarning(
4547 'Header using the wrong include guard name %s' % guard_name,
4548 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574549 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144550 else:
4551 # The line after #ifndef should have a #define of the same name.
4552 if line_number == guard_line_number + 1:
4553 expected_line = '#define %s' % guard_name
4554 if line != expected_line:
4555 errors.append(output_api.PresubmitPromptWarning(
4556 'Missing "%s" for include guard' % expected_line,
4557 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4558 'Expected: %r\nGot: %r' % (expected_line, line)))
4559
4560 if not seen_guard_end and line == '#endif // %s' % guard_name:
4561 seen_guard_end = True
4562 elif seen_guard_end:
4563 if line.strip() != '':
4564 errors.append(output_api.PresubmitPromptWarning(
4565 'Include guard %s not covering the whole file' % (
4566 guard_name), [f.LocalPath()]))
4567 break # Nothing else to check and enough to warn once.
4568
4569 if guard_name is None:
4570 errors.append(output_api.PresubmitPromptWarning(
4571 'Missing include guard %s' % expected_guard,
4572 [f.LocalPath()],
4573 'Missing include guard in %s\n'
4574 'Recommended name: %s\n'
4575 'This check can be disabled by having the string\n'
4576 'no-include-guard-because-multiply-included in the header.' %
4577 (f.LocalPath(), expected_guard)))
4578
4579 return errors
4580
4581
mostynbb639aca52015-01-07 20:31:234582def _CheckForWindowsLineEndings(input_api, output_api):
4583 """Check source code and known ascii text files for Windows style line
4584 endings.
4585 """
earthdok1b5e0ee2015-03-10 15:19:104586 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234587
4588 file_inclusion_pattern = (
4589 known_text_files,
4590 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4591 )
4592
mostynbb639aca52015-01-07 20:31:234593 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534594 source_file_filter = lambda f: input_api.FilterSourceFile(
4595 f, white_list=file_inclusion_pattern, black_list=None)
4596 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504597 include_file = False
4598 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234599 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504600 include_file = True
4601 if include_file:
4602 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234603
4604 if problems:
4605 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4606 'these files to contain Windows style line endings?\n' +
4607 '\n'.join(problems))]
4608
4609 return []
4610
4611
Vaclav Brozekd5de76a2018-03-17 07:57:504612def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134613 """Checks that all source files use SYSLOG properly."""
4614 syslog_files = []
4615 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564616 for line_number, line in f.ChangedContents():
4617 if 'SYSLOG' in line:
4618 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4619
pastarmovj89f7ee12016-09-20 14:58:134620 if syslog_files:
4621 return [output_api.PresubmitPromptWarning(
4622 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4623 ' calls.\nFiles to check:\n', items=syslog_files)]
4624 return []
4625
4626
[email protected]1f7b4172010-01-28 01:17:344627def CheckChangeOnUpload(input_api, output_api):
4628 results = []
4629 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474630 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284631 results.extend(
jam93a6ee792017-02-08 23:59:224632 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194633 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224634 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134635 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164636 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534637 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194638 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274639 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544640 return results
[email protected]ca8d1982009-02-19 16:33:124641
4642
[email protected]1bfb8322014-04-23 01:02:414643def GetTryServerMasterForBot(bot):
4644 """Returns the Try Server master for the given bot.
4645
[email protected]0bb112362014-07-26 04:38:324646 It tries to guess the master from the bot name, but may still fail
4647 and return None. There is no longer a default master.
4648 """
4649 # Potentially ambiguous bot names are listed explicitly.
4650 master_map = {
tandriie5587792016-07-14 00:34:504651 'chromium_presubmit': 'master.tryserver.chromium.linux',
4652 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414653 }
[email protected]0bb112362014-07-26 04:38:324654 master = master_map.get(bot)
4655 if not master:
wnwen4fbaab82016-05-25 12:54:364656 if 'android' in bot:
tandriie5587792016-07-14 00:34:504657 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364658 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504659 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324660 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504661 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324662 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504663 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324664 return master
[email protected]1bfb8322014-04-23 01:02:414665
4666
[email protected]ca8d1982009-02-19 16:33:124667def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544668 results = []
[email protected]1f7b4172010-01-28 01:17:344669 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574670 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544671 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274672 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344673 input_api,
4674 output_api,
[email protected]2fdd1f362013-01-16 03:56:034675 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274676
jam93a6ee792017-02-08 23:59:224677 results.extend(
4678 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544679 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4680 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384681 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4682 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414683 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4684 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544685 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144686
4687
4688def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144689 import os
4690 import sys
4691 from io import StringIO
4692
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144693 new_or_added_paths = set(f.LocalPath()
4694 for f in input_api.AffectedFiles()
4695 if (f.Action() == 'A' or f.Action() == 'M'))
4696 removed_paths = set(f.LocalPath()
4697 for f in input_api.AffectedFiles(include_deletes=True)
4698 if f.Action() == 'D')
4699
4700 affected_grds = [f for f in input_api.AffectedFiles()
4701 if (f.LocalPath().endswith('.grd') or
4702 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164703 if not affected_grds:
4704 return []
4705
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144706 affected_png_paths = [f.AbsoluteLocalPath()
4707 for f in input_api.AffectedFiles()
4708 if (f.LocalPath().endswith('.png'))]
4709
4710 # Check for screenshots. Developers can upload screenshots using
4711 # tools/translation/upload_screenshots.py which finds and uploads
4712 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4713 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4714 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4715 #
4716 # The logic here is as follows:
4717 #
4718 # - If the CL has a .png file under the screenshots directory for a grd
4719 # file, warn the developer. Actual images should never be checked into the
4720 # Chrome repo.
4721 #
4722 # - If the CL contains modified or new messages in grd files and doesn't
4723 # contain the corresponding .sha1 files, warn the developer to add images
4724 # and upload them via tools/translation/upload_screenshots.py.
4725 #
4726 # - If the CL contains modified or new messages in grd files and the
4727 # corresponding .sha1 files, everything looks good.
4728 #
4729 # - If the CL contains removed messages in grd files but the corresponding
4730 # .sha1 files aren't removed, warn the developer to remove them.
4731 unnecessary_screenshots = []
4732 missing_sha1 = []
4733 unnecessary_sha1_files = []
4734
4735
4736 def _CheckScreenshotAdded(screenshots_dir, message_id):
4737 sha1_path = input_api.os_path.join(
4738 screenshots_dir, message_id + '.png.sha1')
4739 if sha1_path not in new_or_added_paths:
4740 missing_sha1.append(sha1_path)
4741
4742
4743 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4744 sha1_path = input_api.os_path.join(
4745 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034746 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144747 unnecessary_sha1_files.append(sha1_path)
4748
meacer8c0d3832019-12-26 21:46:164749 try:
4750 old_sys_path = sys.path
4751 sys.path = sys.path + [input_api.os_path.join(
4752 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4753 from helper import grd_helper
4754 finally:
4755 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144756
4757 for f in affected_grds:
4758 file_path = f.LocalPath()
4759 old_id_to_msg_map = {}
4760 new_id_to_msg_map = {}
Mustafa Emre Acerd697ac92020-02-06 19:03:384761 # Note that this code doesn't check if the file has been deleted. This is
4762 # OK because it only uses the old and new file contents and doesn't load
4763 # the file via its path.
4764 # It's also possible that a file's content refers to a renamed or deleted
4765 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
4766 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
4767 # .grdp files.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144768 if file_path.endswith('.grdp'):
4769 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584770 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394771 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144772 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584773 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394774 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144775 else:
meacerff8a9b62019-12-10 19:43:584776 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144777 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584778 old_id_to_msg_map = grd_helper.GetGrdMessages(
4779 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144780 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584781 new_id_to_msg_map = grd_helper.GetGrdMessages(
4782 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144783
4784 # Compute added, removed and modified message IDs.
4785 old_ids = set(old_id_to_msg_map)
4786 new_ids = set(new_id_to_msg_map)
4787 added_ids = new_ids - old_ids
4788 removed_ids = old_ids - new_ids
4789 modified_ids = set([])
4790 for key in old_ids.intersection(new_ids):
4791 if (old_id_to_msg_map[key].FormatXml()
4792 != new_id_to_msg_map[key].FormatXml()):
4793 modified_ids.add(key)
4794
4795 grd_name, ext = input_api.os_path.splitext(
4796 input_api.os_path.basename(file_path))
4797 screenshots_dir = input_api.os_path.join(
4798 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4799
4800 # Check the screenshot directory for .png files. Warn if there is any.
4801 for png_path in affected_png_paths:
4802 if png_path.startswith(screenshots_dir):
4803 unnecessary_screenshots.append(png_path)
4804
4805 for added_id in added_ids:
4806 _CheckScreenshotAdded(screenshots_dir, added_id)
4807
4808 for modified_id in modified_ids:
4809 _CheckScreenshotAdded(screenshots_dir, modified_id)
4810
4811 for removed_id in removed_ids:
4812 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4813
4814 results = []
4815 if unnecessary_screenshots:
4816 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394817 'Do not include actual screenshots in the changelist. Run '
4818 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144819 sorted(unnecessary_screenshots)))
4820
4821 if missing_sha1:
4822 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394823 'You are adding or modifying UI strings.\n'
4824 'To ensure the best translations, take screenshots of the relevant UI '
4825 '(https://g.co/chrome/translation) and add these files to your '
4826 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144827
4828 if unnecessary_sha1_files:
4829 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394830 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144831 sorted(unnecessary_sha1_files)))
4832
4833 return results