blob: b90150beaf332d118318ba8e87d09a4290d003a9 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0413 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py",
14 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py",
15 r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
16 r"^net[\\/]tools[\\/]spdyshark[\\/].*",
17 r"^skia[\\/].*",
Kent Tamura32dbbcb2018-11-30 12:28:4918 r"^third_party[\\/]blink[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0419 r"^third_party[\\/]breakpad[\\/].*",
Darwin Huangd74a9d32019-07-17 17:58:4620 # sqlite is an imported third party dependency.
21 r"^third_party[\\/]sqlite[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0422 r"^v8[\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5324 r".+_autogen\.h$",
John Budorick1e701d322019-09-11 23:35:1225 r".+_pb2\.py$",
Egor Paskoce145c42018-09-28 19:31:0426 r".+[\\/]pnacl_shim\.c$",
27 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
Egor Paskoce145c42018-09-28 19:31:0428 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1429 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0430 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5431 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0432 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4033)
[email protected]ca8d1982009-02-19 16:33:1234
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Fragment of a regular expression that matches C++ and Objective-C++
37# implementation files.
38_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
39
wnwenbdc444e2016-05-25 13:44:1540
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1941# Fragment of a regular expression that matches C++ and Objective-C++
42# header files.
43_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
44
45
[email protected]06e6d0ff2012-12-11 01:36:4446# Regular expression that matches code only used for test binaries
47# (best effort).
48_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0449 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4450 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4451 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1252 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1853 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4454 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0455 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0556 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0457 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4758 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0459 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0860 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0461 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4162 # EarlGrey app side code for tests.
63 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4464)
[email protected]ca8d1982009-02-19 16:33:1265
Daniel Bratell609102be2019-03-27 20:53:2166_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1567
[email protected]eea609a2011-11-18 13:10:1268_TEST_ONLY_WARNING = (
69 'You might be calling functions intended only for testing from\n'
70 'production code. It is OK to ignore this warning if you know what\n'
71 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0772 'not perfect. The commit queue will not block on this warning,\n'
73 'however the android-binary-size trybot will block if the method\n'
74 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1275
76
[email protected]cf9b78f2012-11-14 11:40:2877_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4078 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2179 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
80 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2881
Michael Thiessen44457642020-02-06 00:24:1582# Format: Sequence of tuples containing:
83# * Full import path.
84# * Sequence of strings to show when the pattern matches.
85# * Sequence of path or filename exceptions to this rule
86_BANNED_JAVA_IMPORTS = (
87 (
Colin Blundell170d78c82020-03-12 13:56:0488 'java.net.URI;',
Michael Thiessen44457642020-02-06 00:24:1589 (
90 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
91 ),
92 (
93 'net/android/javatests/src/org/chromium/net/'
94 'AndroidProxySelectorTest.java',
95 'components/cronet/',
96 ),
97 ),
98)
wnwenbdc444e2016-05-25 13:44:1599
Daniel Bratell609102be2019-03-27 20:53:21100# Format: Sequence of tuples containing:
101# * String pattern or, if starting with a slash, a regular expression.
102# * Sequence of strings to show when the pattern matches.
103# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:41104_BANNED_JAVA_FUNCTIONS = (
105 (
106 'StrictMode.allowThreadDiskReads()',
107 (
108 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
109 'directly.',
110 ),
111 False,
112 ),
113 (
114 'StrictMode.allowThreadDiskWrites()',
115 (
116 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
117 'directly.',
118 ),
119 False,
120 ),
121)
122
Daniel Bratell609102be2019-03-27 20:53:21123# Format: Sequence of tuples containing:
124# * String pattern or, if starting with a slash, a regular expression.
125# * Sequence of strings to show when the pattern matches.
126# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59127_BANNED_OBJC_FUNCTIONS = (
128 (
129 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59132 'prohibited. Please use CrTrackingArea instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 False,
136 ),
137 (
[email protected]eaae1972014-04-16 04:17:26138 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20139 (
140 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59141 'instead.',
142 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
143 ),
144 False,
145 ),
146 (
147 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20148 (
149 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59150 'Please use |convertPoint:(point) fromView:nil| instead.',
151 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
152 ),
153 True,
154 ),
155 (
156 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59159 'Please use |convertPoint:(point) toView:nil| instead.',
160 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
161 ),
162 True,
163 ),
164 (
165 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59168 'Please use |convertRect:(point) fromView:nil| instead.',
169 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
170 ),
171 True,
172 ),
173 (
174 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20175 (
176 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59177 'Please use |convertRect:(point) toView:nil| instead.',
178 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
179 ),
180 True,
181 ),
182 (
183 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20184 (
185 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59186 'Please use |convertSize:(point) fromView:nil| instead.',
187 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
188 ),
189 True,
190 ),
191 (
192 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20193 (
194 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59195 'Please use |convertSize:(point) toView:nil| instead.',
196 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
197 ),
198 True,
199 ),
jif65398702016-10-27 10:19:48200 (
201 r"/\s+UTF8String\s*]",
202 (
203 'The use of -[NSString UTF8String] is dangerous as it can return null',
204 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
205 'Please use |SysNSStringToUTF8| instead.',
206 ),
207 True,
208 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34209 (
210 r'__unsafe_unretained',
211 (
212 'The use of __unsafe_unretained is almost certainly wrong, unless',
213 'when interacting with NSFastEnumeration or NSInvocation.',
214 'Please use __weak in files build with ARC, nothing otherwise.',
215 ),
216 False,
217 ),
Avi Drissman7382afa02019-04-29 23:27:13218 (
219 'freeWhenDone:NO',
220 (
221 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
222 'Foundation types is prohibited.',
223 ),
224 True,
225 ),
[email protected]127f18ec2012-06-16 05:05:59226)
227
Daniel Bratell609102be2019-03-27 20:53:21228# Format: Sequence of tuples containing:
229# * String pattern or, if starting with a slash, a regular expression.
230# * Sequence of strings to show when the pattern matches.
231# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54232_BANNED_IOS_OBJC_FUNCTIONS = (
233 (
234 r'/\bTEST[(]',
235 (
236 'TEST() macro should not be used in Objective-C++ code as it does not ',
237 'drain the autorelease pool at the end of the test. Use TEST_F() ',
238 'macro instead with a fixture inheriting from PlatformTest (or a ',
239 'typedef).'
240 ),
241 True,
242 ),
243 (
244 r'/\btesting::Test\b',
245 (
246 'testing::Test should not be used in Objective-C++ code as it does ',
247 'not drain the autorelease pool at the end of the test. Use ',
248 'PlatformTest instead.'
249 ),
250 True,
251 ),
252)
253
Peter K. Lee6c03ccff2019-07-15 14:40:05254# Format: Sequence of tuples containing:
255# * String pattern or, if starting with a slash, a regular expression.
256# * Sequence of strings to show when the pattern matches.
257# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
258_BANNED_IOS_EGTEST_FUNCTIONS = (
259 (
260 r'/\bEXPECT_OCMOCK_VERIFY\b',
261 (
262 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
263 'it is meant for GTests. Use [mock verify] instead.'
264 ),
265 True,
266 ),
267)
268
danakj7a2b7082019-05-21 21:13:51269# Directories that contain deprecated Bind() or Callback types.
270# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36271# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51272# echo "-- $i"
danakj710b4c02019-11-28 16:08:45273# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51274# done
275#
276# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
277# when they have been converted to modern callback types (OnceCallback,
278# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
279# checks for them and prevent regressions.
280_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
danakj7a2b7082019-05-21 21:13:51281 '^apps/',
danakj7a2b7082019-05-21 21:13:51282 '^base/callback.h', # Intentional.
283 '^chrome/app/',
284 '^chrome/browser/',
285 '^chrome/chrome_elf/',
danakj7a2b7082019-05-21 21:13:51286 '^chrome/common/',
287 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51288 '^chrome/renderer/',
289 '^chrome/services/',
290 '^chrome/test/',
291 '^chrome/tools/',
292 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51293 '^chromecast/media/',
294 '^chromecast/metrics/',
295 '^chromecast/net/',
296 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51297 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51298 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51299 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51300 '^components/arc/',
301 '^components/assist_ranker/',
302 '^components/autofill/',
303 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51304 '^components/browser_watcher/',
danakj7a2b7082019-05-21 21:13:51305 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51306 '^components/chromeos_camera/',
307 '^components/component_updater/',
308 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51309 '^components/cronet/',
310 '^components/data_reduction_proxy/',
danakj7a2b7082019-05-21 21:13:51311 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36312 '^components/dom_distiller/',
Joey Scarr164d7072020-04-21 03:13:39313 '^components/download/internal/common/',
danakj7a2b7082019-05-21 21:13:51314 '^components/drive/',
315 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51316 '^components/feature_engagement/',
317 '^components/feedback/',
318 '^components/flags_ui/',
319 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51320 '^components/guest_view/',
321 '^components/heap_profiling/',
322 '^components/history/',
323 '^components/image_fetcher/',
324 '^components/invalidation/',
325 '^components/keyed_service/',
326 '^components/login/',
327 '^components/metrics/',
328 '^components/metrics_services_manager/',
329 '^components/nacl/',
330 '^components/navigation_interception/',
331 '^components/net_log/',
332 '^components/network_time/',
333 '^components/ntp_snippets/',
334 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51335 '^components/offline_pages/',
336 '^components/omnibox/',
337 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51338 '^components/password_manager/',
339 '^components/payments/',
340 '^components/plugins/',
341 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51342 '^components/proxy_config/',
343 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51344 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51345 '^components/rlz/',
346 '^components/safe_browsing/',
347 '^components/search_engines/',
348 '^components/search_provider_logos/',
349 '^components/security_interstitials/',
350 '^components/security_state/',
351 '^components/services/',
352 '^components/sessions/',
353 '^components/signin/',
354 '^components/ssl_errors/',
355 '^components/storage_monitor/',
356 '^components/subresource_filter/',
357 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51358 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51359 '^components/sync_preferences/',
360 '^components/sync_sessions/',
361 '^components/test/',
362 '^components/tracing/',
363 '^components/translate/',
364 '^components/ukm/',
365 '^components/update_client/',
366 '^components/upload_list/',
367 '^components/variations/',
368 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51369 '^components/webcrypto/',
370 '^components/webdata/',
371 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51372 '^device/bluetooth/',
Alan Cutter04a00642020-03-02 01:45:20373 '^extensions/browser/',
374 '^extensions/renderer/',
danakj7a2b7082019-05-21 21:13:51375 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51376 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51377 '^ios/chrome/',
378 '^ios/components/',
379 '^ios/net/',
380 '^ios/web/',
381 '^ios/web_view/',
382 '^ipc/',
danakj7a2b7082019-05-21 21:13:51383 '^media/base/',
danakjc8576092019-11-26 19:01:36384 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51385 '^media/cast/',
386 '^media/cdm/',
387 '^media/device_monitors/',
danakj7a2b7082019-05-21 21:13:51388 '^media/filters/',
389 '^media/formats/',
390 '^media/gpu/',
391 '^media/mojo/',
danakj7a2b7082019-05-21 21:13:51392 '^media/renderers/',
danakj7a2b7082019-05-21 21:13:51393 '^net/',
394 '^ppapi/proxy/',
395 '^ppapi/shared_impl/',
396 '^ppapi/tests/',
397 '^ppapi/thunk/',
398 '^remoting/base/',
399 '^remoting/client/',
danakj7a2b7082019-05-21 21:13:51400 '^remoting/host/',
401 '^remoting/internal/',
danakj7a2b7082019-05-21 21:13:51402 '^remoting/protocol/',
danakj7a2b7082019-05-21 21:13:51403 '^services/',
danakj7a2b7082019-05-21 21:13:51404 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51405 '^tools/clang/base_bind_rewriters/', # Intentional.
406 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51407))
[email protected]127f18ec2012-06-16 05:05:59408
Daniel Bratell609102be2019-03-27 20:53:21409# Format: Sequence of tuples containing:
410# * String pattern or, if starting with a slash, a regular expression.
411# * Sequence of strings to show when the pattern matches.
412# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
413# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59414_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20415 (
Dave Tapuska98199b612019-07-10 13:30:44416 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53417 (
418 'New code should not use NULL. Use nullptr instead.',
419 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20420 False,
thomasandersone7caaa9b2017-03-29 19:22:53421 (),
422 ),
Peter Kasting94a56c42019-10-25 21:54:04423 (
424 r'/\busing namespace ',
425 (
426 'Using directives ("using namespace x") are banned by the Google Style',
427 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
428 'Explicitly qualify symbols or use using declarations ("using x::foo").',
429 ),
430 True,
431 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
432 ),
Antonio Gomes07300d02019-03-13 20:59:57433 # Make sure that gtest's FRIEND_TEST() macro is not used; the
434 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
435 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53436 (
[email protected]23e6cbc2012-06-16 18:51:20437 'FRIEND_TEST(',
438 (
[email protected]e3c945502012-06-26 20:01:49439 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20440 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
441 ),
442 False,
[email protected]7345da02012-11-27 14:31:49443 (),
[email protected]23e6cbc2012-06-16 18:51:20444 ),
445 (
Dave Tapuska98199b612019-07-10 13:30:44446 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53447 (
448 'Chrome clients wishing to select events on X windows should use',
449 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
450 'you are selecting events from the GPU process, or if you are using',
451 'an XDisplay other than gfx::GetXDisplay().',
452 ),
453 True,
454 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40455 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04456 r"^ui[\\/]gl[\\/].*\.cc$",
457 r"^media[\\/]gpu[\\/].*\.cc$",
458 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53459 ),
460 ),
461 (
Dave Tapuska98199b612019-07-10 13:30:44462 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20463 (
thomasanderson11aa41d2017-06-08 22:22:38464 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20465 ),
466 True,
467 (
Egor Paskoce145c42018-09-28 19:31:04468 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
469 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
470 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20471 ),
472 ),
473 (
tomhudsone2c14d552016-05-26 17:07:46474 'setMatrixClip',
475 (
476 'Overriding setMatrixClip() is prohibited; ',
477 'the base function is deprecated. ',
478 ),
479 True,
480 (),
481 ),
482 (
[email protected]52657f62013-05-20 05:30:31483 'SkRefPtr',
484 (
485 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22486 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31487 ),
488 True,
489 (),
490 ),
491 (
492 'SkAutoRef',
493 (
494 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22495 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31496 ),
497 True,
498 (),
499 ),
500 (
501 'SkAutoTUnref',
502 (
503 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22504 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31505 ),
506 True,
507 (),
508 ),
509 (
510 'SkAutoUnref',
511 (
512 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
513 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22514 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31515 ),
516 True,
517 (),
518 ),
[email protected]d89eec82013-12-03 14:10:59519 (
520 r'/HANDLE_EINTR\(.*close',
521 (
522 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
523 'descriptor will be closed, and it is incorrect to retry the close.',
524 'Either call close directly and ignore its return value, or wrap close',
525 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
526 ),
527 True,
528 (),
529 ),
530 (
531 r'/IGNORE_EINTR\((?!.*close)',
532 (
533 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
534 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
535 ),
536 True,
537 (
538 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04539 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
540 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59541 ),
542 ),
[email protected]ec5b3f02014-04-04 18:43:43543 (
544 r'/v8::Extension\(',
545 (
546 'Do not introduce new v8::Extensions into the code base, use',
547 'gin::Wrappable instead. See http://crbug.com/334679',
548 ),
549 True,
[email protected]f55c90ee62014-04-12 00:50:03550 (
Egor Paskoce145c42018-09-28 19:31:04551 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03552 ),
[email protected]ec5b3f02014-04-04 18:43:43553 ),
skyostilf9469f72015-04-20 10:38:52554 (
jame2d1a952016-04-02 00:27:10555 '#pragma comment(lib,',
556 (
557 'Specify libraries to link with in build files and not in the source.',
558 ),
559 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41560 (
tzik3f295992018-12-04 20:32:23561 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04562 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41563 ),
jame2d1a952016-04-02 00:27:10564 ),
fdorayc4ac18d2017-05-01 21:39:59565 (
Gabriel Charette7cc6c432018-04-25 20:52:02566 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59567 (
568 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
569 ),
570 False,
571 (),
572 ),
573 (
Gabriel Charette7cc6c432018-04-25 20:52:02574 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59575 (
576 'Consider using THREAD_CHECKER macros instead of the class directly.',
577 ),
578 False,
579 (),
580 ),
dbeamb6f4fde2017-06-15 04:03:06581 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06582 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
583 (
584 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
585 'deprecated (http://crbug.com/634507). Please avoid converting away',
586 'from the Time types in Chromium code, especially if any math is',
587 'being done on time values. For interfacing with platform/library',
588 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
589 'type converter methods instead. For faking TimeXXX values (for unit',
590 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
591 'other use cases, please contact base/time/OWNERS.',
592 ),
593 False,
594 (),
595 ),
596 (
dbeamb6f4fde2017-06-15 04:03:06597 'CallJavascriptFunctionUnsafe',
598 (
599 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
600 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
601 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
602 ),
603 False,
604 (
Egor Paskoce145c42018-09-28 19:31:04605 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
606 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
607 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06608 ),
609 ),
dskiba1474c2bfd62017-07-20 02:19:24610 (
611 'leveldb::DB::Open',
612 (
613 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
614 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
615 "Chrome's tracing, making their memory usage visible.",
616 ),
617 True,
618 (
619 r'^third_party/leveldatabase/.*\.(cc|h)$',
620 ),
Gabriel Charette0592c3a2017-07-26 12:02:04621 ),
622 (
Chris Mumfordc38afb62017-10-09 17:55:08623 'leveldb::NewMemEnv',
624 (
625 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58626 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
627 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08628 ),
629 True,
630 (
631 r'^third_party/leveldatabase/.*\.(cc|h)$',
632 ),
633 ),
634 (
Gabriel Charetted9839bc2017-07-29 14:17:47635 'RunLoop::QuitCurrent',
636 (
Robert Liao64b7ab22017-08-04 23:03:43637 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
638 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47639 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41640 False,
Gabriel Charetted9839bc2017-07-29 14:17:47641 (),
Gabriel Charettea44975052017-08-21 23:14:04642 ),
643 (
644 'base::ScopedMockTimeMessageLoopTaskRunner',
645 (
Gabriel Charette87cc1af2018-04-25 20:52:51646 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11647 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51648 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
649 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
650 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04651 ),
Gabriel Charette87cc1af2018-04-25 20:52:51652 False,
Gabriel Charettea44975052017-08-21 23:14:04653 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57654 ),
655 (
Dave Tapuska98199b612019-07-10 13:30:44656 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57657 (
658 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02659 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57660 ),
661 True,
662 (),
Francois Doray43670e32017-09-27 12:40:38663 ),
664 (
Peter Kasting991618a62019-06-17 22:00:09665 r'/\bstd::stoi\b',
666 (
667 'std::stoi uses exceptions to communicate results. ',
668 'Use base::StringToInt() instead.',
669 ),
670 True,
671 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
672 ),
673 (
674 r'/\bstd::stol\b',
675 (
676 'std::stol uses exceptions to communicate results. ',
677 'Use base::StringToInt() instead.',
678 ),
679 True,
680 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
681 ),
682 (
683 r'/\bstd::stoul\b',
684 (
685 'std::stoul uses exceptions to communicate results. ',
686 'Use base::StringToUint() instead.',
687 ),
688 True,
689 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
690 ),
691 (
692 r'/\bstd::stoll\b',
693 (
694 'std::stoll uses exceptions to communicate results. ',
695 'Use base::StringToInt64() instead.',
696 ),
697 True,
698 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
699 ),
700 (
701 r'/\bstd::stoull\b',
702 (
703 'std::stoull uses exceptions to communicate results. ',
704 'Use base::StringToUint64() instead.',
705 ),
706 True,
707 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
708 ),
709 (
710 r'/\bstd::stof\b',
711 (
712 'std::stof uses exceptions to communicate results. ',
713 'For locale-independent values, e.g. reading numbers from disk',
714 'profiles, use base::StringToDouble().',
715 'For user-visible values, parse using ICU.',
716 ),
717 True,
718 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
719 ),
720 (
721 r'/\bstd::stod\b',
722 (
723 'std::stod uses exceptions to communicate results. ',
724 'For locale-independent values, e.g. reading numbers from disk',
725 'profiles, use base::StringToDouble().',
726 'For user-visible values, parse using ICU.',
727 ),
728 True,
729 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
730 ),
731 (
732 r'/\bstd::stold\b',
733 (
734 'std::stold uses exceptions to communicate results. ',
735 'For locale-independent values, e.g. reading numbers from disk',
736 'profiles, use base::StringToDouble().',
737 'For user-visible values, parse using ICU.',
738 ),
739 True,
740 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
741 ),
742 (
Daniel Bratell69334cc2019-03-26 11:07:45743 r'/\bstd::to_string\b',
744 (
745 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09746 'For locale-independent strings, e.g. writing numbers to disk',
747 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45748 'For user-visible strings, use base::FormatNumber() and',
749 'the related functions in base/i18n/number_formatting.h.',
750 ),
Peter Kasting991618a62019-06-17 22:00:09751 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21752 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45753 ),
754 (
755 r'/\bstd::shared_ptr\b',
756 (
757 'std::shared_ptr should not be used. Use scoped_refptr instead.',
758 ),
759 True,
Andreas Haas63f58792019-11-07 10:56:44760 [_THIRD_PARTY_EXCEPT_BLINK,
761 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
762 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21763 ),
764 (
Peter Kasting991618a62019-06-17 22:00:09765 r'/\bstd::weak_ptr\b',
766 (
767 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
768 ),
769 True,
770 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
771 ),
772 (
Daniel Bratell609102be2019-03-27 20:53:21773 r'/\blong long\b',
774 (
775 'long long is banned. Use stdint.h if you need a 64 bit number.',
776 ),
777 False, # Only a warning since it is already used.
778 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
779 ),
780 (
781 r'/\bstd::bind\b',
782 (
783 'std::bind is banned because of lifetime risks.',
784 'Use base::BindOnce or base::BindRepeating instead.',
785 ),
786 True,
787 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
788 ),
789 (
790 r'/\b#include <chrono>\b',
791 (
792 '<chrono> overlaps with Time APIs in base. Keep using',
793 'base classes.',
794 ),
795 True,
796 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
797 ),
798 (
799 r'/\b#include <exception>\b',
800 (
801 'Exceptions are banned and disabled in Chromium.',
802 ),
803 True,
804 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
805 ),
806 (
807 r'/\bstd::function\b',
808 (
809 'std::function is banned. Instead use base::Callback which directly',
810 'supports Chromium\'s weak pointers, ref counting and more.',
811 ),
Peter Kasting991618a62019-06-17 22:00:09812 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21813 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
814 ),
815 (
816 r'/\b#include <random>\b',
817 (
818 'Do not use any random number engines from <random>. Instead',
819 'use base::RandomBitGenerator.',
820 ),
821 True,
822 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
823 ),
824 (
825 r'/\bstd::ratio\b',
826 (
827 'std::ratio is banned by the Google Style Guide.',
828 ),
829 True,
830 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45831 ),
832 (
Francois Doray43670e32017-09-27 12:40:38833 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
834 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
835 (
836 'Use the new API in base/threading/thread_restrictions.h.',
837 ),
Gabriel Charette04b138f2018-08-06 00:03:22838 False,
Francois Doray43670e32017-09-27 12:40:38839 (),
840 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38841 (
danakj7a2b7082019-05-21 21:13:51842 r'/\bbase::Bind\(',
843 (
844 'Please use base::Bind{Once,Repeating} instead',
845 'of base::Bind. (crbug.com/714018)',
846 ),
847 False,
Erik Staaba737d7602019-11-25 18:41:07848 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51849 ),
850 (
851 r'/\bbase::Callback[<:]',
852 (
853 'Please use base::{Once,Repeating}Callback instead',
854 'of base::Callback. (crbug.com/714018)',
855 ),
856 False,
Erik Staaba737d7602019-11-25 18:41:07857 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51858 ),
859 (
860 r'/\bbase::Closure\b',
861 (
862 'Please use base::{Once,Repeating}Closure instead',
863 'of base::Closure. (crbug.com/714018)',
864 ),
865 False,
Erik Staaba737d7602019-11-25 18:41:07866 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51867 ),
868 (
Michael Giuffrida7f93d6922019-04-19 14:39:58869 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19870 (
871 'RunMessageLoop is deprecated, use RunLoop instead.',
872 ),
873 False,
874 (),
875 ),
876 (
Dave Tapuska98199b612019-07-10 13:30:44877 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19878 (
879 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
880 ),
881 False,
882 (),
883 ),
884 (
Dave Tapuska98199b612019-07-10 13:30:44885 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19886 (
887 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
888 "if you're convinced you need this.",
889 ),
890 False,
891 (),
892 ),
893 (
Dave Tapuska98199b612019-07-10 13:30:44894 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19895 (
896 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04897 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19898 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
899 'async events instead of flushing threads.',
900 ),
901 False,
902 (),
903 ),
904 (
905 r'MessageLoopRunner',
906 (
907 'MessageLoopRunner is deprecated, use RunLoop instead.',
908 ),
909 False,
910 (),
911 ),
912 (
Dave Tapuska98199b612019-07-10 13:30:44913 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19914 (
915 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
916 "gab@ if you found a use case where this is the only solution.",
917 ),
918 False,
919 (),
920 ),
921 (
Victor Costane48a2e82019-03-15 22:02:34922 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16923 (
Victor Costane48a2e82019-03-15 22:02:34924 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16925 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
926 ),
927 True,
928 (
929 r'^sql/initialization\.(cc|h)$',
930 r'^third_party/sqlite/.*\.(c|cc|h)$',
931 ),
932 ),
Matt Menke7f520a82018-03-28 21:38:37933 (
Dave Tapuska98199b612019-07-10 13:30:44934 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47935 (
936 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
937 'base::RandomShuffle instead.'
938 ),
939 True,
940 (),
941 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24942 (
943 'ios/web/public/test/http_server',
944 (
945 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
946 ),
947 False,
948 (),
949 ),
Robert Liao764c9492019-01-24 18:46:28950 (
951 'GetAddressOf',
952 (
953 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46954 'implicated in a few leaks. Use operator& instead. See ',
955 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28956 ),
957 True,
958 (),
959 ),
Antonio Gomes07300d02019-03-13 20:59:57960 (
961 'DEFINE_TYPE_CASTS',
962 (
963 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
964 '//third_party/blink/renderer/platform/casting.h.'
965 ),
966 True,
967 (
968 r'^third_party/blink/renderer/.*\.(cc|h)$',
969 ),
970 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38971 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45972 r'/\bIsHTML.+Element\(\b',
973 (
974 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
975 ' helpers IsA<HTMLXXXXElement> from ',
976 '//third_party/blink/renderer/platform/casting.h.'
977 ),
978 False,
979 (
980 r'^third_party/blink/renderer/.*\.(cc|h)$',
981 ),
982 ),
983 (
984 r'/\bToHTML.+Element(|OrNull)\(\b',
985 (
986 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
987 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
988 'and DynamicTo<HTMLXXXXElement> from ',
989 '//third_party/blink/renderer/platform/casting.h.'
990 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
991 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
992 ),
993 False,
994 (
995 r'^third_party/blink/renderer/.*\.(cc|h)$',
996 ),
997 ),
998 (
Kinuko Yasuda376c2ce12019-04-16 01:20:37999 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381000 (
1001 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1002 ),
1003 True,
1004 (),
1005 ),
Ben Lewisa9514602019-04-29 17:53:051006 (
1007 'SHFileOperation',
1008 (
1009 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1010 'complex functions to achieve the same goals. Use IFileOperation for ',
1011 'any esoteric actions instead.'
1012 ),
1013 True,
1014 (),
1015 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181016 (
Cliff Smolinsky81951642019-04-30 21:39:511017 'StringFromGUID2',
1018 (
1019 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1020 'Use base::win::String16FromGUID instead.'
1021 ),
1022 True,
1023 (
1024 r'/base/win/win_util_unittest.cc'
1025 ),
1026 ),
1027 (
1028 'StringFromCLSID',
1029 (
1030 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1031 'Use base::win::String16FromGUID instead.'
1032 ),
1033 True,
1034 (
1035 r'/base/win/win_util_unittest.cc'
1036 ),
1037 ),
1038 (
Avi Drissman7382afa02019-04-29 23:27:131039 'kCFAllocatorNull',
1040 (
1041 'The use of kCFAllocatorNull with the NoCopy creation of ',
1042 'CoreFoundation types is prohibited.',
1043 ),
1044 True,
1045 (),
1046 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291047 (
1048 'mojo::ConvertTo',
1049 (
1050 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1051 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1052 'StringTraits if you would like to convert between custom types and',
1053 'the wire format of mojom types.'
1054 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221055 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291056 (
Wezf89dec092019-09-11 19:38:331057 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1058 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291059 r'^third_party/blink/.*\.(cc|h)$',
1060 r'^content/renderer/.*\.(cc|h)$',
1061 ),
1062 ),
Robert Liao1d78df52019-11-11 20:02:011063 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161064 'GetInterfaceProvider',
1065 (
1066 'InterfaceProvider is deprecated.',
1067 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1068 'or Platform::GetBrowserInterfaceBroker.'
1069 ),
1070 False,
1071 (),
1072 ),
1073 (
Robert Liao1d78df52019-11-11 20:02:011074 'CComPtr',
1075 (
1076 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1077 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1078 'details.'
1079 ),
1080 False,
1081 (),
1082 ),
Xiaohan Wang72bd2ba2020-02-18 21:38:201083 (
1084 r'/\b(IFACE|STD)METHOD_?\(',
1085 (
1086 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1087 'Instead, always use IFACEMETHODIMP in the declaration.'
1088 ),
1089 False,
1090 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1091 ),
Allen Bauer53b43fb12020-03-12 17:21:471092 (
1093 'set_owned_by_client',
1094 (
1095 'set_owned_by_client is deprecated.',
1096 'views::View already owns the child views by default. This introduces ',
1097 'a competing ownership model which makes the code difficult to reason ',
1098 'about. See http://crbug.com/1044687 for more details.'
1099 ),
1100 False,
1101 (),
1102 ),
[email protected]127f18ec2012-06-16 05:05:591103)
1104
Mario Sanchez Prada2472cab2019-09-18 10:58:311105# Format: Sequence of tuples containing:
1106# * String pattern or, if starting with a slash, a regular expression.
1107# * Sequence of strings to show when the pattern matches.
1108_DEPRECATED_MOJO_TYPES = (
1109 (
1110 r'/\bmojo::AssociatedBinding\b',
1111 (
1112 'mojo::AssociatedBinding<Interface> is deprecated.',
1113 'Use mojo::AssociatedReceiver<Interface> instead.',
1114 ),
1115 ),
1116 (
1117 r'/\bmojo::AssociatedBindingSet\b',
1118 (
1119 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1120 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1121 ),
1122 ),
1123 (
1124 r'/\bmojo::AssociatedInterfacePtr\b',
1125 (
1126 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1127 'Use mojo::AssociatedRemote<Interface> instead.',
1128 ),
1129 ),
1130 (
1131 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1132 (
1133 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1134 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1135 ),
1136 ),
1137 (
1138 r'/\bmojo::AssociatedInterfaceRequest\b',
1139 (
1140 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1141 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1142 ),
1143 ),
1144 (
1145 r'/\bmojo::Binding\b',
1146 (
1147 'mojo::Binding<Interface> is deprecated.',
1148 'Use mojo::Receiver<Interface> instead.',
1149 ),
1150 ),
1151 (
1152 r'/\bmojo::BindingSet\b',
1153 (
1154 'mojo::BindingSet<Interface> is deprecated.',
1155 'Use mojo::ReceiverSet<Interface> instead.',
1156 ),
1157 ),
1158 (
1159 r'/\bmojo::InterfacePtr\b',
1160 (
1161 'mojo::InterfacePtr<Interface> is deprecated.',
1162 'Use mojo::Remote<Interface> instead.',
1163 ),
1164 ),
1165 (
1166 r'/\bmojo::InterfacePtrInfo\b',
1167 (
1168 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1169 'Use mojo::PendingRemote<Interface> instead.',
1170 ),
1171 ),
1172 (
1173 r'/\bmojo::InterfaceRequest\b',
1174 (
1175 'mojo::InterfaceRequest<Interface> is deprecated.',
1176 'Use mojo::PendingReceiver<Interface> instead.',
1177 ),
1178 ),
1179 (
1180 r'/\bmojo::MakeRequest\b',
1181 (
1182 'mojo::MakeRequest is deprecated.',
1183 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1184 ),
1185 ),
1186 (
1187 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1188 (
1189 'mojo::MakeRequest is deprecated.',
1190 'Use mojo::AssociatedRemote::'
1191 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1192 ),
1193 ),
1194 (
1195 r'/\bmojo::MakeStrongBinding\b',
1196 (
1197 'mojo::MakeStrongBinding is deprecated.',
1198 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1199 'mojo::MakeSelfOwnedReceiver() instead.',
1200 ),
1201 ),
1202 (
1203 r'/\bmojo::MakeStrongAssociatedBinding\b',
1204 (
1205 'mojo::MakeStrongAssociatedBinding is deprecated.',
1206 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1207 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1208 ),
1209 ),
1210 (
1211 r'/\bmojo::StrongAssociatedBindingSet\b',
1212 (
1213 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1214 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1215 ),
1216 ),
1217 (
1218 r'/\bmojo::StrongBindingSet\b',
1219 (
1220 'mojo::StrongBindingSet<Interface> is deprecated.',
1221 'Use mojo::UniqueReceiverSet<Interface> instead.',
1222 ),
1223 ),
1224)
wnwenbdc444e2016-05-25 13:44:151225
mlamouria82272622014-09-16 18:45:041226_IPC_ENUM_TRAITS_DEPRECATED = (
1227 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501228 'See http://www.chromium.org/Home/chromium-security/education/'
1229 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041230
Stephen Martinis97a394142018-06-07 23:06:051231_LONG_PATH_ERROR = (
1232 'Some files included in this CL have file names that are too long (> 200'
1233 ' characters). If committed, these files will cause issues on Windows. See'
1234 ' https://crbug.com/612667 for more details.'
1235)
1236
Shenghua Zhangbfaa38b82017-11-16 21:58:021237_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041238 r".*[\\/]BuildHooksAndroidImpl\.java",
1239 r".*[\\/]LicenseContentProvider\.java",
1240 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281241 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021242]
[email protected]127f18ec2012-06-16 05:05:591243
Mohamed Heikald048240a2019-11-12 16:57:371244# List of image extensions that are used as resources in chromium.
1245_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1246
Sean Kau46e29bc2017-08-28 16:31:161247# These paths contain test data and other known invalid JSON files.
Erik Staab2dd72b12020-04-16 15:03:401248_KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041249 r'test[\\/]data[\\/]',
Erik Staab2dd72b12020-04-16 15:03:401250 r'testing[\\/]buildbot[\\/]',
Egor Paskoce145c42018-09-28 19:31:041251 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1252 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041253 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431254 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161255]
1256
1257
[email protected]b00342e7f2013-03-26 16:21:541258_VALID_OS_MACROS = (
1259 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081260 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541261 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121262 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541263 'OS_BSD',
1264 'OS_CAT', # For testing.
1265 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041266 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541267 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371268 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541269 'OS_IOS',
1270 'OS_LINUX',
1271 'OS_MACOSX',
1272 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211273 'OS_NACL_NONSFI',
1274 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121275 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541276 'OS_OPENBSD',
1277 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371278 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541280 'OS_WIN',
1281)
1282
1283
agrievef32bcc72016-04-04 14:57:401284_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391285 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361286 'base/android/jni_generator/jni_generator.pydeps',
1287 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221288 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361289 'build/android/gyp/aar.pydeps',
1290 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271291 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361292 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381293 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361294 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111295 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361296 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361297 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361298 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111299 'build/android/gyp/create_app_bundle_apks.pydeps',
1300 'build/android/gyp/create_app_bundle.pydeps',
1301 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361302 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221303 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591305 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361306 'build/android/gyp/dex.pydeps',
Andrew Grieve723c1502020-04-23 16:27:421307 'build/android/gyp/dex_jdk_libs.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361309 'build/android/gyp/filter_zip.pydeps',
1310 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361311 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361312 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581313 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361314 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261315 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve5853fbd2020-02-20 17:26:011316 'build/android/gyp/jetify_jar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361317 'build/android/gyp/jinja_template.pydeps',
1318 'build/android/gyp/lint.pydeps',
1319 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361320 'build/android/gyp/merge_manifest.pydeps',
1321 'build/android/gyp/prepare_resources.pydeps',
1322 'build/android/gyp/proguard.pydeps',
Peter Wen578730b2020-03-19 19:55:461323 'build/android/gyp/turbine.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241324 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361325 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461326 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561327 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361328 'build/android/incremental_install/generate_android_manifest.pydeps',
1329 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221330 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401331 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041332 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361333 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411334 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051335 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191336 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431337 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021338 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401339]
1340
wnwenbdc444e2016-05-25 13:44:151341
agrievef32bcc72016-04-04 14:57:401342_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421343 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131344 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421345 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1346 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131347 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191348 ('third_party/blink/renderer/bindings/scripts/'
1349 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061350 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221351 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401352]
1353
wnwenbdc444e2016-05-25 13:44:151354
agrievef32bcc72016-04-04 14:57:401355_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1356
1357
Eric Boren6fd2b932018-01-25 15:05:081358# Bypass the AUTHORS check for these accounts.
1359_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591360 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451361 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591362 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521363 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1364 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041365 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271366 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041367 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301368 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081369
1370
Daniel Bratell65b033262019-04-23 08:17:061371def _IsCPlusPlusFile(input_api, file_path):
1372 """Returns True if this file contains C++-like code (and not Python,
1373 Go, Java, MarkDown, ...)"""
1374
1375 ext = input_api.os_path.splitext(file_path)[1]
1376 # This list is compatible with CppChecker.IsCppFile but we should
1377 # consider adding ".c" to it. If we do that we can use this function
1378 # at more places in the code.
1379 return ext in (
1380 '.h',
1381 '.cc',
1382 '.cpp',
1383 '.m',
1384 '.mm',
1385 )
1386
1387def _IsCPlusPlusHeaderFile(input_api, file_path):
1388 return input_api.os_path.splitext(file_path)[1] == ".h"
1389
1390
1391def _IsJavaFile(input_api, file_path):
1392 return input_api.os_path.splitext(file_path)[1] == ".java"
1393
1394
1395def _IsProtoFile(input_api, file_path):
1396 return input_api.os_path.splitext(file_path)[1] == ".proto"
1397
[email protected]55459852011-08-10 15:17:191398def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1399 """Attempts to prevent use of functions intended only for testing in
1400 non-testing code. For now this is just a best-effort implementation
1401 that ignores header files and may have some false positives. A
1402 better implementation would probably need a proper C++ parser.
1403 """
1404 # We only scan .cc files and the like, as the declaration of
1405 # for-testing functions in header files are hard to distinguish from
1406 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491407 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191408
jochenc0d4808c2015-07-27 09:25:421409 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191410 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091411 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191412 exclusion_pattern = input_api.re.compile(
1413 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1414 base_function_pattern, base_function_pattern))
1415
1416 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441417 black_list = (_EXCLUDED_PATHS +
1418 _TEST_CODE_EXCLUDED_PATHS +
1419 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191420 return input_api.FilterSourceFile(
1421 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491422 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191423 black_list=black_list)
1424
1425 problems = []
1426 for f in input_api.AffectedSourceFiles(FilterFile):
1427 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241428 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031429 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461430 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031431 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191432 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031433 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191434
1435 if problems:
[email protected]f7051d52013-04-02 18:31:421436 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031437 else:
1438 return []
[email protected]55459852011-08-10 15:17:191439
1440
Vaclav Brozek7dbc28c2018-03-27 08:35:231441def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1442 """This is a simplified version of
1443 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1444 """
1445 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1446 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1447 name_pattern = r'ForTest(s|ing)?'
1448 # Describes an occurrence of "ForTest*" inside a // comment.
1449 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1450 # Catch calls.
1451 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1452 # Ignore definitions. (Comments are ignored separately.)
1453 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1454
1455 problems = []
1456 sources = lambda x: input_api.FilterSourceFile(
1457 x,
1458 black_list=(('(?i).*test', r'.*\/junit\/')
1459 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491460 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231461 )
1462 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1463 local_path = f.LocalPath()
1464 is_inside_javadoc = False
1465 for line_number, line in f.ChangedContents():
1466 if is_inside_javadoc and javadoc_end_re.search(line):
1467 is_inside_javadoc = False
1468 if not is_inside_javadoc and javadoc_start_re.search(line):
1469 is_inside_javadoc = True
1470 if is_inside_javadoc:
1471 continue
1472 if (inclusion_re.search(line) and
1473 not comment_re.search(line) and
1474 not exclusion_re.search(line)):
1475 problems.append(
1476 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1477
1478 if problems:
1479 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1480 else:
1481 return []
1482
1483
[email protected]10689ca2011-09-02 02:31:541484def _CheckNoIOStreamInHeaders(input_api, output_api):
1485 """Checks to make sure no .h files include <iostream>."""
1486 files = []
1487 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1488 input_api.re.MULTILINE)
1489 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1490 if not f.LocalPath().endswith('.h'):
1491 continue
1492 contents = input_api.ReadFile(f)
1493 if pattern.search(contents):
1494 files.append(f)
1495
1496 if len(files):
yolandyandaabc6d2016-04-18 18:29:391497 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061498 'Do not #include <iostream> in header files, since it inserts static '
1499 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541500 '#include <ostream>. See http://crbug.com/94794',
1501 files) ]
1502 return []
1503
Danil Chapovalov3518f362018-08-11 16:13:431504def _CheckNoStrCatRedefines(input_api, output_api):
1505 """Checks no windows headers with StrCat redefined are included directly."""
1506 files = []
1507 pattern_deny = input_api.re.compile(
1508 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1509 input_api.re.MULTILINE)
1510 pattern_allow = input_api.re.compile(
1511 r'^#include\s"base/win/windows_defines.inc"',
1512 input_api.re.MULTILINE)
1513 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1514 contents = input_api.ReadFile(f)
1515 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1516 files.append(f.LocalPath())
1517
1518 if len(files):
1519 return [output_api.PresubmitError(
1520 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1521 'directly since they pollute code with StrCat macro. Instead, '
1522 'include matching header from base/win. See http://crbug.com/856536',
1523 files) ]
1524 return []
1525
[email protected]10689ca2011-09-02 02:31:541526
[email protected]72df4e782012-06-21 16:28:181527def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521528 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181529 problems = []
1530 for f in input_api.AffectedFiles():
1531 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1532 continue
1533
1534 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041535 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181536 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1537
1538 if not problems:
1539 return []
1540 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1541 '\n'.join(problems))]
1542
Dominic Battre033531052018-09-24 15:45:341543def _CheckNoDISABLETypoInTests(input_api, output_api):
1544 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1545
1546 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1547 instead of DISABLED_. To filter false positives, reports are only generated
1548 if a corresponding MAYBE_ line exists.
1549 """
1550 problems = []
1551
1552 # The following two patterns are looked for in tandem - is a test labeled
1553 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1554 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1555 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1556
1557 # This is for the case that a test is disabled on all platforms.
1558 full_disable_pattern = input_api.re.compile(
1559 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1560 input_api.re.MULTILINE)
1561
Katie Df13948e2018-09-25 07:33:441562 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341563 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1564 continue
1565
1566 # Search for MABYE_, DISABLE_ pairs.
1567 disable_lines = {} # Maps of test name to line number.
1568 maybe_lines = {}
1569 for line_num, line in f.ChangedContents():
1570 disable_match = disable_pattern.search(line)
1571 if disable_match:
1572 disable_lines[disable_match.group(1)] = line_num
1573 maybe_match = maybe_pattern.search(line)
1574 if maybe_match:
1575 maybe_lines[maybe_match.group(1)] = line_num
1576
1577 # Search for DISABLE_ occurrences within a TEST() macro.
1578 disable_tests = set(disable_lines.keys())
1579 maybe_tests = set(maybe_lines.keys())
1580 for test in disable_tests.intersection(maybe_tests):
1581 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1582
1583 contents = input_api.ReadFile(f)
1584 full_disable_match = full_disable_pattern.search(contents)
1585 if full_disable_match:
1586 problems.append(' %s' % f.LocalPath())
1587
1588 if not problems:
1589 return []
1590 return [
1591 output_api.PresubmitPromptWarning(
1592 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1593 '\n'.join(problems))
1594 ]
1595
[email protected]72df4e782012-06-21 16:28:181596
danakj61c1aa22015-10-26 19:55:521597def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571598 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521599 errors = []
1600 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1601 input_api.re.MULTILINE)
1602 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1603 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1604 continue
1605 for lnum, line in f.ChangedContents():
1606 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171607 errors.append(output_api.PresubmitError(
1608 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571609 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171610 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521611 return errors
1612
1613
Makoto Shimazu3ad422cd2019-05-08 02:35:141614def _FindHistogramNameInChunk(histogram_name, chunk):
1615 """Tries to find a histogram name or prefix in a line.
1616
1617 Returns the existence of the histogram name, or None if it needs more chunk
1618 to determine."""
mcasasb7440c282015-02-04 14:52:191619 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1620 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141621 if '<affected-histogram' in chunk:
1622 # If the tag is not completed, needs more chunk to get the name.
1623 if not '>' in chunk:
1624 return None
1625 if not 'name="' in chunk:
1626 return False
1627 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1628 # expect the only attribute is the name.
1629 histogram_prefix = chunk.split('"')[1]
1630 return histogram_prefix in histogram_name
1631 # Typically the whole histogram name should in the line.
1632 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191633
1634
1635def _CheckUmaHistogramChanges(input_api, output_api):
1636 """Check that UMA histogram names in touched lines can still be found in other
1637 lines of the patch or in histograms.xml. Note that this check would not catch
1638 the reverse: changes in histograms.xml not matched in the code itself."""
1639 touched_histograms = []
1640 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471641 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1642 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1643 name_pattern = r'"(.*?)"'
1644 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1645 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1646 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1647 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1648 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171649 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191650 for f in input_api.AffectedFiles():
1651 # If histograms.xml itself is modified, keep the modified lines for later.
1652 if f.LocalPath().endswith(('histograms.xml')):
1653 histograms_xml_modifications = f.ChangedContents()
1654 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471655 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1656 single_line_re = single_line_c_re
1657 split_line_prefix_re = split_line_c_prefix_re
1658 elif f.LocalPath().endswith(('java')):
1659 single_line_re = single_line_java_re
1660 split_line_prefix_re = split_line_java_prefix_re
1661 else:
mcasasb7440c282015-02-04 14:52:191662 continue
1663 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171664 if last_line_matched_prefix:
1665 suffix_found = split_line_suffix_re.search(line)
1666 if suffix_found :
1667 touched_histograms.append([suffix_found.group(1), f, line_num])
1668 last_line_matched_prefix = False
1669 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061670 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191671 if found:
1672 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171673 continue
1674 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191675
1676 # Search for the touched histogram names in the local modifications to
1677 # histograms.xml, and, if not found, on the base histograms.xml file.
1678 unmatched_histograms = []
1679 for histogram_info in touched_histograms:
1680 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141681 chunk = ''
mcasasb7440c282015-02-04 14:52:191682 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141683 chunk += line
1684 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1685 if histogram_name_found is None:
1686 continue
1687 chunk = ''
mcasasb7440c282015-02-04 14:52:191688 if histogram_name_found:
1689 break
1690 if not histogram_name_found:
1691 unmatched_histograms.append(histogram_info)
1692
eromanb90c82e7e32015-04-01 15:13:491693 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191694 problems = []
1695 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491696 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191697 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451698 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191699 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141700 chunk = ''
mcasasb7440c282015-02-04 14:52:191701 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141702 chunk += line
1703 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1704 chunk)
1705 if histogram_name_found is None:
1706 continue
1707 chunk = ''
mcasasb7440c282015-02-04 14:52:191708 if histogram_name_found:
1709 break
1710 if not histogram_name_found:
1711 problems.append(' [%s:%d] %s' %
1712 (f.LocalPath(), line_num, histogram_name))
1713
1714 if not problems:
1715 return []
1716 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1717 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491718 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191719
wnwenbdc444e2016-05-25 13:44:151720
yolandyandaabc6d2016-04-18 18:29:391721def _CheckFlakyTestUsage(input_api, output_api):
1722 """Check that FlakyTest annotation is our own instead of the android one"""
1723 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1724 files = []
1725 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1726 if f.LocalPath().endswith('Test.java'):
1727 if pattern.search(input_api.ReadFile(f)):
1728 files.append(f)
1729 if len(files):
1730 return [output_api.PresubmitError(
1731 'Use org.chromium.base.test.util.FlakyTest instead of '
1732 'android.test.FlakyTest',
1733 files)]
1734 return []
mcasasb7440c282015-02-04 14:52:191735
wnwenbdc444e2016-05-25 13:44:151736
[email protected]8ea5d4b2011-09-13 21:49:221737def _CheckNoNewWStrings(input_api, output_api):
1738 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271739 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221740 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201741 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571742 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341743 '/win/' in f.LocalPath() or
1744 'chrome_elf' in f.LocalPath() or
1745 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201746 continue
[email protected]8ea5d4b2011-09-13 21:49:221747
[email protected]a11dbe9b2012-08-07 01:32:581748 allowWString = False
[email protected]b5c24292011-11-28 14:38:201749 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581750 if 'presubmit: allow wstring' in line:
1751 allowWString = True
1752 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271753 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581754 allowWString = False
1755 else:
1756 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221757
[email protected]55463aa62011-10-12 00:48:271758 if not problems:
1759 return []
1760 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581761 ' If you are calling a cross-platform API that accepts a wstring, '
1762 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271763 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221764
1765
[email protected]2a8ac9c2011-10-19 17:20:441766def _CheckNoDEPSGIT(input_api, output_api):
1767 """Make sure .DEPS.git is never modified manually."""
1768 if any(f.LocalPath().endswith('.DEPS.git') for f in
1769 input_api.AffectedFiles()):
1770 return [output_api.PresubmitError(
1771 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1772 'automated system based on what\'s in DEPS and your changes will be\n'
1773 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501774 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1775 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441776 'for more information')]
1777 return []
1778
1779
tandriief664692014-09-23 14:51:471780def _CheckValidHostsInDEPS(input_api, output_api):
1781 """Checks that DEPS file deps are from allowed_hosts."""
1782 # Run only if DEPS file has been modified to annoy fewer bystanders.
1783 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1784 return []
1785 # Outsource work to gclient verify
1786 try:
John Budorickf20c0042019-04-25 23:23:401787 gclient_path = input_api.os_path.join(
1788 input_api.PresubmitLocalPath(),
1789 'third_party', 'depot_tools', 'gclient.py')
1790 input_api.subprocess.check_output(
1791 [input_api.python_executable, gclient_path, 'verify'],
1792 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471793 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201794 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471795 return [output_api.PresubmitError(
1796 'DEPS file must have only git dependencies.',
1797 long_text=error.output)]
1798
1799
Mario Sanchez Prada2472cab2019-09-18 10:58:311800def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1801 type_name, message):
1802 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1803
1804 Returns an string composed of the name of the file, the line number where the
1805 match has been found and the additional text passed as |message| in case the
1806 target type name matches the text inside the line passed as parameter.
1807 """
1808 matched = False
1809 if type_name[0:1] == '/':
1810 regex = type_name[1:]
1811 if input_api.re.search(regex, line):
1812 matched = True
1813 elif type_name in line:
1814 matched = True
1815
1816 result = []
1817 if matched:
1818 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1819 for message_line in message:
1820 result.append(' %s' % message_line)
1821
1822 return result
1823
1824
[email protected]127f18ec2012-06-16 05:05:591825def _CheckNoBannedFunctions(input_api, output_api):
1826 """Make sure that banned functions are not used."""
1827 warnings = []
1828 errors = []
1829
wnwenbdc444e2016-05-25 13:44:151830 def IsBlacklisted(affected_file, blacklist):
1831 local_path = affected_file.LocalPath()
1832 for item in blacklist:
1833 if input_api.re.match(item, local_path):
1834 return True
1835 return False
1836
Peter K. Lee6c03ccff2019-07-15 14:40:051837 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541838 local_path = affected_file.LocalPath()
1839 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1840 return False
1841 basename = input_api.os_path.basename(local_path)
1842 if 'ios' in basename.split('_'):
1843 return True
1844 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1845 if sep and 'ios' in local_path.split(sep):
1846 return True
1847 return False
1848
wnwenbdc444e2016-05-25 13:44:151849 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311850 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1851 func_name, message)
1852 if problems:
wnwenbdc444e2016-05-25 13:44:151853 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311854 errors.extend(problems)
1855 else:
1856 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151857
Eric Stevensona9a980972017-09-23 00:04:411858 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1859 for f in input_api.AffectedFiles(file_filter=file_filter):
1860 for line_num, line in f.ChangedContents():
1861 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1862 CheckForMatch(f, line_num, line, func_name, message, error)
1863
[email protected]127f18ec2012-06-16 05:05:591864 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1865 for f in input_api.AffectedFiles(file_filter=file_filter):
1866 for line_num, line in f.ChangedContents():
1867 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151868 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591869
Peter K. Lee6c03ccff2019-07-15 14:40:051870 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541871 for line_num, line in f.ChangedContents():
1872 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1873 CheckForMatch(f, line_num, line, func_name, message, error)
1874
Peter K. Lee6c03ccff2019-07-15 14:40:051875 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1876 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1877 for line_num, line in f.ChangedContents():
1878 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1879 CheckForMatch(f, line_num, line, func_name, message, error)
1880
[email protected]127f18ec2012-06-16 05:05:591881 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1882 for f in input_api.AffectedFiles(file_filter=file_filter):
1883 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491884 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491885 if IsBlacklisted(f, excluded_paths):
1886 continue
wnwenbdc444e2016-05-25 13:44:151887 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591888
1889 result = []
1890 if (warnings):
1891 result.append(output_api.PresubmitPromptWarning(
1892 'Banned functions were used.\n' + '\n'.join(warnings)))
1893 if (errors):
1894 result.append(output_api.PresubmitError(
1895 'Banned functions were used.\n' + '\n'.join(errors)))
1896 return result
1897
1898
Michael Thiessen44457642020-02-06 00:24:151899def _CheckAndroidNoBannedImports(input_api, output_api):
1900 """Make sure that banned java imports are not used."""
1901 errors = []
1902
1903 def IsException(path, exceptions):
1904 for exception in exceptions:
1905 if (path.startswith(exception)):
1906 return True
1907 return False
1908
1909 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1910 for f in input_api.AffectedFiles(file_filter=file_filter):
1911 for line_num, line in f.ChangedContents():
1912 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1913 if IsException(f.LocalPath(), exceptions):
1914 continue;
1915 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1916 'import ' + import_name, message)
1917 if problems:
1918 errors.extend(problems)
1919 result = []
1920 if (errors):
1921 result.append(output_api.PresubmitError(
1922 'Banned imports were used.\n' + '\n'.join(errors)))
1923 return result
1924
1925
Mario Sanchez Prada2472cab2019-09-18 10:58:311926def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1927 """Make sure that old Mojo types are not used."""
1928 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571929 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311930
Mario Sanchez Pradaaab91382019-12-19 08:57:091931 # For any path that is not an "ok" or an "error" path, a warning will be
1932 # raised if deprecated mojo types are found.
1933 ok_paths = ['components/arc']
1934 error_paths = ['third_party/blink', 'content']
1935
Mario Sanchez Prada2472cab2019-09-18 10:58:311936 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1937 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571938 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091939 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311940 continue
1941
1942 for line_num, line in f.ChangedContents():
1943 for func_name, message in _DEPRECATED_MOJO_TYPES:
1944 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1945 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571946
Mario Sanchez Prada2472cab2019-09-18 10:58:311947 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091948 # Raise errors inside |error_paths| and warnings everywhere else.
1949 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571950 errors.extend(problems)
1951 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311952 warnings.extend(problems)
1953
1954 result = []
1955 if (warnings):
1956 result.append(output_api.PresubmitPromptWarning(
1957 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571958 if (errors):
1959 result.append(output_api.PresubmitError(
1960 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311961 return result
1962
1963
[email protected]6c063c62012-07-11 19:11:061964def _CheckNoPragmaOnce(input_api, output_api):
1965 """Make sure that banned functions are not used."""
1966 files = []
1967 pattern = input_api.re.compile(r'^#pragma\s+once',
1968 input_api.re.MULTILINE)
1969 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1970 if not f.LocalPath().endswith('.h'):
1971 continue
1972 contents = input_api.ReadFile(f)
1973 if pattern.search(contents):
1974 files.append(f)
1975
1976 if files:
1977 return [output_api.PresubmitError(
1978 'Do not use #pragma once in header files.\n'
1979 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1980 files)]
1981 return []
1982
[email protected]127f18ec2012-06-16 05:05:591983
[email protected]e7479052012-09-19 00:26:121984def _CheckNoTrinaryTrueFalse(input_api, output_api):
1985 """Checks to make sure we don't introduce use of foo ? true : false."""
1986 problems = []
1987 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1988 for f in input_api.AffectedFiles():
1989 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1990 continue
1991
1992 for line_num, line in f.ChangedContents():
1993 if pattern.match(line):
1994 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1995
1996 if not problems:
1997 return []
1998 return [output_api.PresubmitPromptWarning(
1999 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2000 '\n'.join(problems))]
2001
2002
[email protected]55f9f382012-07-31 11:02:182003def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282004 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182005 change. Breaking - rules is an error, breaking ! rules is a
2006 warning.
2007 """
mohan.reddyf21db962014-10-16 12:26:472008 import sys
[email protected]55f9f382012-07-31 11:02:182009 # We need to wait until we have an input_api object and use this
2010 # roundabout construct to import checkdeps because this file is
2011 # eval-ed and thus doesn't have __file__.
2012 original_sys_path = sys.path
2013 try:
2014 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472015 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182016 import checkdeps
[email protected]55f9f382012-07-31 11:02:182017 from rules import Rule
2018 finally:
2019 # Restore sys.path to what it was before.
2020 sys.path = original_sys_path
2021
2022 added_includes = []
rhalavati08acd232017-04-03 07:23:282023 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242024 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182025 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062026 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502027 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082028 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062029 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502030 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082031 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062032 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502033 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082034 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182035
[email protected]26385172013-05-09 23:11:352036 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182037
2038 error_descriptions = []
2039 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282040 error_subjects = set()
2041 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182042 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2043 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082044 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182045 description_with_path = '%s\n %s' % (path, rule_description)
2046 if rule_type == Rule.DISALLOW:
2047 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282048 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182049 else:
2050 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282051 warning_subjects.add("#includes")
2052
2053 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2054 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082055 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282056 description_with_path = '%s\n %s' % (path, rule_description)
2057 if rule_type == Rule.DISALLOW:
2058 error_descriptions.append(description_with_path)
2059 error_subjects.add("imports")
2060 else:
2061 warning_descriptions.append(description_with_path)
2062 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182063
Jinsuk Kim5a092672017-10-24 22:42:242064 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022065 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082066 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242067 description_with_path = '%s\n %s' % (path, rule_description)
2068 if rule_type == Rule.DISALLOW:
2069 error_descriptions.append(description_with_path)
2070 error_subjects.add("imports")
2071 else:
2072 warning_descriptions.append(description_with_path)
2073 warning_subjects.add("imports")
2074
[email protected]55f9f382012-07-31 11:02:182075 results = []
2076 if error_descriptions:
2077 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282078 'You added one or more %s that violate checkdeps rules.'
2079 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182080 error_descriptions))
2081 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422082 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282083 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182084 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282085 '%s? See relevant DEPS file(s) for details and contacts.' %
2086 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182087 warning_descriptions))
2088 return results
2089
2090
[email protected]fbcafe5a2012-08-08 15:31:222091def _CheckFilePermissions(input_api, output_api):
2092 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152093 if input_api.platform == 'win32':
2094 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292095 checkperms_tool = input_api.os_path.join(
2096 input_api.PresubmitLocalPath(),
2097 'tools', 'checkperms', 'checkperms.py')
2098 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472099 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392100 with input_api.CreateTemporaryFile() as file_list:
2101 for f in input_api.AffectedFiles():
2102 # checkperms.py file/directory arguments must be relative to the
2103 # repository.
2104 file_list.write(f.LocalPath() + '\n')
2105 file_list.close()
2106 args += ['--file-list', file_list.name]
2107 try:
2108 input_api.subprocess.check_output(args)
2109 return []
2110 except input_api.subprocess.CalledProcessError as error:
2111 return [output_api.PresubmitError(
2112 'checkperms.py failed:',
2113 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222114
2115
robertocn832f5992017-01-04 19:01:302116def _CheckTeamTags(input_api, output_api):
2117 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2118 checkteamtags_tool = input_api.os_path.join(
2119 input_api.PresubmitLocalPath(),
2120 'tools', 'checkteamtags', 'checkteamtags.py')
2121 args = [input_api.python_executable, checkteamtags_tool,
2122 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222123 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302124 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2125 'OWNERS']
2126 try:
2127 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052128 warnings = input_api.subprocess.check_output(args + files).splitlines()
2129 if warnings:
2130 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302131 return []
2132 except input_api.subprocess.CalledProcessError as error:
2133 return [output_api.PresubmitError(
2134 'checkteamtags.py failed:',
2135 long_text=error.output)]
2136
2137
[email protected]c8278b32012-10-30 20:35:492138def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2139 """Makes sure we don't include ui/aura/window_property.h
2140 in header files.
2141 """
2142 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2143 errors = []
2144 for f in input_api.AffectedFiles():
2145 if not f.LocalPath().endswith('.h'):
2146 continue
2147 for line_num, line in f.ChangedContents():
2148 if pattern.match(line):
2149 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2150
2151 results = []
2152 if errors:
2153 results.append(output_api.PresubmitError(
2154 'Header files should not include ui/aura/window_property.h', errors))
2155 return results
2156
2157
[email protected]70ca77752012-11-20 03:45:032158def _CheckForVersionControlConflictsInFile(input_api, f):
2159 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2160 errors = []
2161 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162162 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232163 # First-level headers in markdown look a lot like version control
2164 # conflict markers. http://daringfireball.net/projects/markdown/basics
2165 continue
[email protected]70ca77752012-11-20 03:45:032166 if pattern.match(line):
2167 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2168 return errors
2169
2170
2171def _CheckForVersionControlConflicts(input_api, output_api):
2172 """Usually this is not intentional and will cause a compile failure."""
2173 errors = []
2174 for f in input_api.AffectedFiles():
2175 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2176
2177 results = []
2178 if errors:
2179 results.append(output_api.PresubmitError(
2180 'Version control conflict markers found, please resolve.', errors))
2181 return results
2182
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202183
estadee17314a02017-01-12 16:22:162184def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2185 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2186 errors = []
2187 for f in input_api.AffectedFiles():
2188 for line_num, line in f.ChangedContents():
2189 if pattern.search(line):
2190 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2191
2192 results = []
2193 if errors:
2194 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502195 'Found Google support URL addressed by answer number. Please replace '
2196 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162197 return results
2198
[email protected]70ca77752012-11-20 03:45:032199
[email protected]06e6d0ff2012-12-11 01:36:442200def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2201 def FilterFile(affected_file):
2202 """Filter function for use with input_api.AffectedSourceFiles,
2203 below. This filters out everything except non-test files from
2204 top-level directories that generally speaking should not hard-code
2205 service URLs (e.g. src/android_webview/, src/content/ and others).
2206 """
2207 return input_api.FilterSourceFile(
2208 affected_file,
Egor Paskoce145c42018-09-28 19:31:042209 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442210 black_list=(_EXCLUDED_PATHS +
2211 _TEST_CODE_EXCLUDED_PATHS +
2212 input_api.DEFAULT_BLACK_LIST))
2213
reillyi38965732015-11-16 18:27:332214 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2215 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462216 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2217 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442218 problems = [] # items are (filename, line_number, line)
2219 for f in input_api.AffectedSourceFiles(FilterFile):
2220 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462221 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442222 problems.append((f.LocalPath(), line_num, line))
2223
2224 if problems:
[email protected]f7051d52013-04-02 18:31:422225 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442226 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582227 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442228 [' %s:%d: %s' % (
2229 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032230 else:
2231 return []
[email protected]06e6d0ff2012-12-11 01:36:442232
2233
James Cook6b6597c2019-11-06 22:05:292234def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2235 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2236 def FileFilter(affected_file):
2237 """Includes directories known to be Chrome OS only."""
2238 return input_api.FilterSourceFile(
2239 affected_file,
2240 white_list=('^ash/',
2241 '^chromeos/', # Top-level src/chromeos.
2242 '/chromeos/', # Any path component.
2243 '^components/arc',
2244 '^components/exo'),
2245 black_list=(input_api.DEFAULT_BLACK_LIST))
2246
2247 prefs = []
2248 priority_prefs = []
2249 for f in input_api.AffectedFiles(file_filter=FileFilter):
2250 for line_num, line in f.ChangedContents():
2251 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2252 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2253 prefs.append(' %s' % line)
2254 if input_api.re.search(
2255 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2256 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2257 priority_prefs.append(' %s' % line)
2258
2259 results = []
2260 if (prefs):
2261 results.append(output_api.PresubmitPromptWarning(
2262 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2263 'by browser sync settings. If these prefs should be controlled by OS '
2264 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2265 if (priority_prefs):
2266 results.append(output_api.PresubmitPromptWarning(
2267 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2268 'controlled by browser sync settings. If these prefs should be '
2269 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2270 'instead.\n' + '\n'.join(prefs)))
2271 return results
2272
2273
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492274# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272275def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2276 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312277 The native_client_sdk directory is excluded because it has auto-generated PNG
2278 files for documentation.
[email protected]d2530012013-01-25 16:39:272279 """
[email protected]d2530012013-01-25 16:39:272280 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492281 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042282 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312283 file_filter = lambda f: input_api.FilterSourceFile(
2284 f, white_list=white_list, black_list=black_list)
2285 for f in input_api.AffectedFiles(include_deletes=False,
2286 file_filter=file_filter):
2287 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272288
2289 results = []
2290 if errors:
2291 results.append(output_api.PresubmitError(
2292 'The name of PNG files should not have abbreviations. \n'
2293 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2294 'Contact [email protected] if you have questions.', errors))
2295 return results
2296
2297
Daniel Cheng4dcdb6b2017-04-13 08:30:172298def _ExtractAddRulesFromParsedDeps(parsed_deps):
2299 """Extract the rules that add dependencies from a parsed DEPS file.
2300
2301 Args:
2302 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2303 add_rules = set()
2304 add_rules.update([
2305 rule[1:] for rule in parsed_deps.get('include_rules', [])
2306 if rule.startswith('+') or rule.startswith('!')
2307 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502308 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172309 {}).iteritems():
2310 add_rules.update([
2311 rule[1:] for rule in rules
2312 if rule.startswith('+') or rule.startswith('!')
2313 ])
2314 return add_rules
2315
2316
2317def _ParseDeps(contents):
2318 """Simple helper for parsing DEPS files."""
2319 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172320 class _VarImpl:
2321
2322 def __init__(self, local_scope):
2323 self._local_scope = local_scope
2324
2325 def Lookup(self, var_name):
2326 """Implements the Var syntax."""
2327 try:
2328 return self._local_scope['vars'][var_name]
2329 except KeyError:
2330 raise Exception('Var is not defined: %s' % var_name)
2331
2332 local_scope = {}
2333 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172334 'Var': _VarImpl(local_scope).Lookup,
2335 }
2336 exec contents in global_scope, local_scope
2337 return local_scope
2338
2339
2340def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082341 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412342 a set of DEPS entries that we should look up.
2343
2344 For a directory (rather than a specific filename) we fake a path to
2345 a specific filename by adding /DEPS. This is chosen as a file that
2346 will seldom or never be subject to per-file include_rules.
2347 """
[email protected]2b438d62013-11-14 17:54:142348 # We ignore deps entries on auto-generated directories.
2349 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082350
Daniel Cheng4dcdb6b2017-04-13 08:30:172351 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2352 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2353
2354 added_deps = new_deps.difference(old_deps)
2355
[email protected]2b438d62013-11-14 17:54:142356 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172357 for added_dep in added_deps:
2358 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2359 continue
2360 # Assume that a rule that ends in .h is a rule for a specific file.
2361 if added_dep.endswith('.h'):
2362 results.add(added_dep)
2363 else:
2364 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082365 return results
2366
2367
[email protected]e871964c2013-05-13 14:14:552368def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2369 """When a dependency prefixed with + is added to a DEPS file, we
2370 want to make sure that the change is reviewed by an OWNER of the
2371 target file or directory, to avoid layering violations from being
2372 introduced. This check verifies that this happens.
2373 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172374 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242375
2376 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492377 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242378 for f in input_api.AffectedFiles(include_deletes=False,
2379 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552380 filename = input_api.os_path.basename(f.LocalPath())
2381 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172382 virtual_depended_on_files.update(_CalculateAddedDeps(
2383 input_api.os_path,
2384 '\n'.join(f.OldContents()),
2385 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552386
[email protected]e871964c2013-05-13 14:14:552387 if not virtual_depended_on_files:
2388 return []
2389
2390 if input_api.is_committing:
2391 if input_api.tbr:
2392 return [output_api.PresubmitNotifyResult(
2393 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272394 if input_api.dry_run:
2395 return [output_api.PresubmitNotifyResult(
2396 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552397 if not input_api.change.issue:
2398 return [output_api.PresubmitError(
2399 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402400 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552401 output = output_api.PresubmitError
2402 else:
2403 output = output_api.PresubmitNotifyResult
2404
2405 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502406 owner_email, reviewers = (
2407 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2408 input_api,
2409 owners_db.email_regexp,
2410 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552411
2412 owner_email = owner_email or input_api.change.author_email
2413
[email protected]de4f7d22013-05-23 14:27:462414 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512415 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462416 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552417 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2418 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412419
2420 # We strip the /DEPS part that was added by
2421 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2422 # directory.
2423 def StripDeps(path):
2424 start_deps = path.rfind('/DEPS')
2425 if start_deps != -1:
2426 return path[:start_deps]
2427 else:
2428 return path
2429 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552430 for path in missing_files]
2431
2432 if unapproved_dependencies:
2433 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152434 output('You need LGTM from owners of depends-on paths in DEPS that were '
2435 'modified in this CL:\n %s' %
2436 '\n '.join(sorted(unapproved_dependencies)))]
2437 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2438 output_list.append(output(
2439 'Suggested missing target path OWNERS:\n %s' %
2440 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552441 return output_list
2442
2443 return []
2444
2445
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492446# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402447def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492448 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402449 black_list = (_EXCLUDED_PATHS +
2450 _TEST_CODE_EXCLUDED_PATHS +
2451 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042452 (r"^base[\\/]logging\.h$",
2453 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222454 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042455 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2456 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2457 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122458 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182459 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152460 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032461 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152462 r"^chrome[\\/]chrome_cleaner[\\/].*",
2463 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2464 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042465 r"^chromecast[\\/]",
2466 r"^cloud_print[\\/]",
2467 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482468 r"dump_stability_report_main_win.cc$",
Sharon Yang5ee61d7e2020-04-15 23:39:052469 r"^components[\\/]media_control[\\/]renderer[\\/]"
2470 r"media_playback_options\.cc$",
Egor Paskoce145c42018-09-28 19:31:042471 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462472 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042473 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462474 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042475 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252476 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042477 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2478 r"^courgette[\\/]courgette_tool\.cc$",
2479 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272480 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002481 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332482 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042483 r"^ipc[\\/]ipc_logging\.cc$",
2484 r"^native_client_sdk[\\/]",
2485 r"^remoting[\\/]base[\\/]logging\.h$",
2486 r"^remoting[\\/]host[\\/].*",
2487 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062488 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332489 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042490 r"^tools[\\/]",
2491 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2492 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332493 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402494 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492495 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402496
thomasanderson625d3932017-03-29 07:16:582497 log_info = set([])
2498 printf = set([])
[email protected]85218562013-11-22 07:41:402499
2500 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582501 for _, line in f.ChangedContents():
2502 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2503 log_info.add(f.LocalPath())
2504 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2505 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372506
thomasanderson625d3932017-03-29 07:16:582507 if input_api.re.search(r"\bprintf\(", line):
2508 printf.add(f.LocalPath())
2509 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2510 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402511
2512 if log_info:
2513 return [output_api.PresubmitError(
2514 'These files spam the console log with LOG(INFO):',
2515 items=log_info)]
2516 if printf:
2517 return [output_api.PresubmitError(
2518 'These files spam the console log with printf/fprintf:',
2519 items=printf)]
2520 return []
2521
2522
[email protected]49aa76a2013-12-04 06:59:162523def _CheckForAnonymousVariables(input_api, output_api):
2524 """These types are all expected to hold locks while in scope and
2525 so should never be anonymous (which causes them to be immediately
2526 destroyed)."""
2527 they_who_must_be_named = [
2528 'base::AutoLock',
2529 'base::AutoReset',
2530 'base::AutoUnlock',
2531 'SkAutoAlphaRestore',
2532 'SkAutoBitmapShaderInstall',
2533 'SkAutoBlitterChoose',
2534 'SkAutoBounderCommit',
2535 'SkAutoCallProc',
2536 'SkAutoCanvasRestore',
2537 'SkAutoCommentBlock',
2538 'SkAutoDescriptor',
2539 'SkAutoDisableDirectionCheck',
2540 'SkAutoDisableOvalCheck',
2541 'SkAutoFree',
2542 'SkAutoGlyphCache',
2543 'SkAutoHDC',
2544 'SkAutoLockColors',
2545 'SkAutoLockPixels',
2546 'SkAutoMalloc',
2547 'SkAutoMaskFreeImage',
2548 'SkAutoMutexAcquire',
2549 'SkAutoPathBoundsUpdate',
2550 'SkAutoPDFRelease',
2551 'SkAutoRasterClipValidate',
2552 'SkAutoRef',
2553 'SkAutoTime',
2554 'SkAutoTrace',
2555 'SkAutoUnref',
2556 ]
2557 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2558 # bad: base::AutoLock(lock.get());
2559 # not bad: base::AutoLock lock(lock.get());
2560 bad_pattern = input_api.re.compile(anonymous)
2561 # good: new base::AutoLock(lock.get())
2562 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2563 errors = []
2564
2565 for f in input_api.AffectedFiles():
2566 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2567 continue
2568 for linenum, line in f.ChangedContents():
2569 if bad_pattern.search(line) and not good_pattern.search(line):
2570 errors.append('%s:%d' % (f.LocalPath(), linenum))
2571
2572 if errors:
2573 return [output_api.PresubmitError(
2574 'These lines create anonymous variables that need to be named:',
2575 items=errors)]
2576 return []
2577
2578
Peter Kasting4844e46e2018-02-23 07:27:102579def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532580 # Returns whether |template_str| is of the form <T, U...> for some types T
2581 # and U. Assumes that |template_str| is already in the form <...>.
2582 def HasMoreThanOneArg(template_str):
2583 # Level of <...> nesting.
2584 nesting = 0
2585 for c in template_str:
2586 if c == '<':
2587 nesting += 1
2588 elif c == '>':
2589 nesting -= 1
2590 elif c == ',' and nesting == 1:
2591 return True
2592 return False
2593
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492594 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102595 sources = lambda affected_file: input_api.FilterSourceFile(
2596 affected_file,
2597 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2598 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492599 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552600
2601 # Pattern to capture a single "<...>" block of template arguments. It can
2602 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2603 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2604 # latter would likely require counting that < and > match, which is not
2605 # expressible in regular languages. Should the need arise, one can introduce
2606 # limited counting (matching up to a total number of nesting depth), which
2607 # should cover all practical cases for already a low nesting limit.
2608 template_arg_pattern = (
2609 r'<[^>]*' # Opening block of <.
2610 r'>([^<]*>)?') # Closing block of >.
2611 # Prefix expressing that whatever follows is not already inside a <...>
2612 # block.
2613 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102614 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552615 not_inside_template_arg_pattern
2616 + r'\bstd::unique_ptr'
2617 + template_arg_pattern
2618 + r'\(\)')
2619
2620 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2621 template_arg_no_array_pattern = (
2622 r'<[^>]*[^]]' # Opening block of <.
2623 r'>([^(<]*[^]]>)?') # Closing block of >.
2624 # Prefix saying that what follows is the start of an expression.
2625 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2626 # Suffix saying that what follows are call parentheses with a non-empty list
2627 # of arguments.
2628 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532629 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552630 return_construct_pattern = input_api.re.compile(
2631 start_of_expr_pattern
2632 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532633 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552634 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532635 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552636 + nonempty_arg_list_pattern)
2637
Vaclav Brozek851d9602018-04-04 16:13:052638 problems_constructor = []
2639 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102640 for f in input_api.AffectedSourceFiles(sources):
2641 for line_number, line in f.ChangedContents():
2642 # Disallow:
2643 # return std::unique_ptr<T>(foo);
2644 # bar = std::unique_ptr<T>(foo);
2645 # But allow:
2646 # return std::unique_ptr<T[]>(foo);
2647 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532648 # And also allow cases when the second template argument is present. Those
2649 # cases cannot be handled by std::make_unique:
2650 # return std::unique_ptr<T, U>(foo);
2651 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052652 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532653 return_construct_result = return_construct_pattern.search(line)
2654 if return_construct_result and not HasMoreThanOneArg(
2655 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052656 problems_constructor.append(
2657 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102658 # Disallow:
2659 # std::unique_ptr<T>()
2660 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052661 problems_nullptr.append(
2662 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2663
2664 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162665 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052666 errors.append(output_api.PresubmitError(
2667 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162668 problems_nullptr))
2669 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052670 errors.append(output_api.PresubmitError(
2671 'The following files use explicit std::unique_ptr constructor.'
2672 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162673 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102674 return errors
2675
2676
[email protected]999261d2014-03-03 20:08:082677def _CheckUserActionUpdate(input_api, output_api):
2678 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522679 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082680 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522681 # If actions.xml is already included in the changelist, the PRESUBMIT
2682 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082683 return []
2684
[email protected]999261d2014-03-03 20:08:082685 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2686 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522687 current_actions = None
[email protected]999261d2014-03-03 20:08:082688 for f in input_api.AffectedFiles(file_filter=file_filter):
2689 for line_num, line in f.ChangedContents():
2690 match = input_api.re.search(action_re, line)
2691 if match:
[email protected]2f92dec2014-03-07 19:21:522692 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2693 # loaded only once.
2694 if not current_actions:
2695 with open('tools/metrics/actions/actions.xml') as actions_f:
2696 current_actions = actions_f.read()
2697 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082698 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522699 action = 'name="{0}"'.format(action_name)
2700 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082701 return [output_api.PresubmitPromptWarning(
2702 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522703 'tools/metrics/actions/actions.xml. Please run '
2704 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082705 % (f.LocalPath(), line_num, action_name))]
2706 return []
2707
2708
Daniel Cheng13ca61a882017-08-25 15:11:252709def _ImportJSONCommentEater(input_api):
2710 import sys
2711 sys.path = sys.path + [input_api.os_path.join(
2712 input_api.PresubmitLocalPath(),
2713 'tools', 'json_comment_eater')]
2714 import json_comment_eater
2715 return json_comment_eater
2716
2717
[email protected]99171a92014-06-03 08:44:472718def _GetJSONParseError(input_api, filename, eat_comments=True):
2719 try:
2720 contents = input_api.ReadFile(filename)
2721 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252722 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132723 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472724
2725 input_api.json.loads(contents)
2726 except ValueError as e:
2727 return e
2728 return None
2729
2730
2731def _GetIDLParseError(input_api, filename):
2732 try:
2733 contents = input_api.ReadFile(filename)
2734 idl_schema = input_api.os_path.join(
2735 input_api.PresubmitLocalPath(),
2736 'tools', 'json_schema_compiler', 'idl_schema.py')
2737 process = input_api.subprocess.Popen(
2738 [input_api.python_executable, idl_schema],
2739 stdin=input_api.subprocess.PIPE,
2740 stdout=input_api.subprocess.PIPE,
2741 stderr=input_api.subprocess.PIPE,
2742 universal_newlines=True)
2743 (_, error) = process.communicate(input=contents)
2744 return error or None
2745 except ValueError as e:
2746 return e
2747
2748
2749def _CheckParseErrors(input_api, output_api):
2750 """Check that IDL and JSON files do not contain syntax errors."""
2751 actions = {
2752 '.idl': _GetIDLParseError,
2753 '.json': _GetJSONParseError,
2754 }
[email protected]99171a92014-06-03 08:44:472755 # Most JSON files are preprocessed and support comments, but these do not.
2756 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042757 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472758 ]
2759 # Only run IDL checker on files in these directories.
2760 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042761 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2762 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472763 ]
2764
2765 def get_action(affected_file):
2766 filename = affected_file.LocalPath()
2767 return actions.get(input_api.os_path.splitext(filename)[1])
2768
[email protected]99171a92014-06-03 08:44:472769 def FilterFile(affected_file):
2770 action = get_action(affected_file)
2771 if not action:
2772 return False
2773 path = affected_file.LocalPath()
2774
Erik Staab2dd72b12020-04-16 15:03:402775 if _MatchesFile(input_api,
2776 _KNOWN_TEST_DATA_AND_INVALID_JSON_FILE_PATTERNS,
2777 path):
[email protected]99171a92014-06-03 08:44:472778 return False
2779
2780 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162781 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472782 return False
2783 return True
2784
2785 results = []
2786 for affected_file in input_api.AffectedFiles(
2787 file_filter=FilterFile, include_deletes=False):
2788 action = get_action(affected_file)
2789 kwargs = {}
2790 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162791 _MatchesFile(input_api, json_no_comments_patterns,
2792 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472793 kwargs['eat_comments'] = False
2794 parse_error = action(input_api,
2795 affected_file.AbsoluteLocalPath(),
2796 **kwargs)
2797 if parse_error:
2798 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2799 (affected_file.LocalPath(), parse_error)))
2800 return results
2801
2802
[email protected]760deea2013-12-10 19:33:492803def _CheckJavaStyle(input_api, output_api):
2804 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472805 import sys
[email protected]760deea2013-12-10 19:33:492806 original_sys_path = sys.path
2807 try:
2808 sys.path = sys.path + [input_api.os_path.join(
2809 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2810 import checkstyle
2811 finally:
2812 # Restore sys.path to what it was before.
2813 sys.path = original_sys_path
2814
2815 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092816 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512817 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492818
2819
Nate Fischerdfd9812e2019-07-18 22:03:002820def _CheckPythonDevilInit(input_api, output_api):
2821 """Checks to make sure devil is initialized correctly in python scripts."""
2822 script_common_initialize_pattern = input_api.re.compile(
2823 r'script_common\.InitializeEnvironment\(')
2824 devil_env_config_initialize = input_api.re.compile(
2825 r'devil_env\.config\.Initialize\(')
2826
2827 errors = []
2828
2829 sources = lambda affected_file: input_api.FilterSourceFile(
2830 affected_file,
2831 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2832 (r'^build[\\/]android[\\/]devil_chromium\.py',
2833 r'^third_party[\\/].*',)),
2834 white_list=[r'.*\.py$'])
2835
2836 for f in input_api.AffectedSourceFiles(sources):
2837 for line_num, line in f.ChangedContents():
2838 if (script_common_initialize_pattern.search(line) or
2839 devil_env_config_initialize.search(line)):
2840 errors.append("%s:%d" % (f.LocalPath(), line_num))
2841
2842 results = []
2843
2844 if errors:
2845 results.append(output_api.PresubmitError(
2846 'Devil initialization should always be done using '
2847 'devil_chromium.Initialize() in the chromium project, to use better '
2848 'defaults for dependencies (ex. up-to-date version of adb).',
2849 errors))
2850
2851 return results
2852
2853
Sean Kau46e29bc2017-08-28 16:31:162854def _MatchesFile(input_api, patterns, path):
2855 for pattern in patterns:
2856 if input_api.re.search(pattern, path):
2857 return True
2858 return False
2859
2860
Daniel Cheng7052cdf2017-11-21 19:23:292861def _GetOwnersFilesToCheckForIpcOwners(input_api):
2862 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172863
Daniel Cheng7052cdf2017-11-21 19:23:292864 Returns:
2865 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2866 contain to cover IPC-related files with noparent reviewer rules.
2867 """
2868 # Whether or not a file affects IPC is (mostly) determined by a simple list
2869 # of filename patterns.
dchenge07de812016-06-20 19:27:172870 file_patterns = [
palmerb19a0932017-01-24 04:00:312871 # Legacy IPC:
dchenge07de812016-06-20 19:27:172872 '*_messages.cc',
2873 '*_messages*.h',
2874 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312875 # Mojo IPC:
dchenge07de812016-06-20 19:27:172876 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472877 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172878 '*_struct_traits*.*',
2879 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312880 '*.typemap',
2881 # Android native IPC:
2882 '*.aidl',
2883 # Blink uses a different file naming convention:
2884 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472885 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172886 '*StructTraits*.*',
2887 '*TypeConverter*.*',
2888 ]
2889
scottmg7a6ed5ba2016-11-04 18:22:042890 # These third_party directories do not contain IPCs, but contain files
2891 # matching the above patterns, which trigger false positives.
2892 exclude_paths = [
2893 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162894 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232895 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292896 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542897 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162898 # These files are just used to communicate between class loaders running
2899 # in the same process.
2900 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572901 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2902
scottmg7a6ed5ba2016-11-04 18:22:042903 ]
2904
dchenge07de812016-06-20 19:27:172905 # Dictionary mapping an OWNERS file path to Patterns.
2906 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2907 # rules ) to a PatternEntry.
2908 # PatternEntry is a dictionary with two keys:
2909 # - 'files': the files that are matched by this pattern
2910 # - 'rules': the per-file rules needed for this pattern
2911 # For example, if we expect OWNERS file to contain rules for *.mojom and
2912 # *_struct_traits*.*, Patterns might look like this:
2913 # {
2914 # '*.mojom': {
2915 # 'files': ...,
2916 # 'rules': [
2917 # 'per-file *.mojom=set noparent',
2918 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2919 # ],
2920 # },
2921 # '*_struct_traits*.*': {
2922 # 'files': ...,
2923 # 'rules': [
2924 # 'per-file *_struct_traits*.*=set noparent',
2925 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2926 # ],
2927 # },
2928 # }
2929 to_check = {}
2930
Daniel Cheng13ca61a882017-08-25 15:11:252931 def AddPatternToCheck(input_file, pattern):
2932 owners_file = input_api.os_path.join(
2933 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2934 if owners_file not in to_check:
2935 to_check[owners_file] = {}
2936 if pattern not in to_check[owners_file]:
2937 to_check[owners_file][pattern] = {
2938 'files': [],
2939 'rules': [
2940 'per-file %s=set noparent' % pattern,
2941 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2942 ]
2943 }
Vaclav Brozekd5de76a2018-03-17 07:57:502944 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252945
dchenge07de812016-06-20 19:27:172946 # Iterate through the affected files to see what we actually need to check
2947 # for. We should only nag patch authors about per-file rules if a file in that
2948 # directory would match that pattern. If a directory only contains *.mojom
2949 # files and no *_messages*.h files, we should only nag about rules for
2950 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252951 for f in input_api.AffectedFiles(include_deletes=False):
Daniel Cheng76f49cc2020-04-21 01:48:262952 # Manifest files don't have a strong naming convention. Instead, try to find
2953 # affected .cc and .h files which look like they contain a manifest
2954 # definition.
2955 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2956 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2957 if (manifest_pattern.search(f.LocalPath()) and not
2958 test_manifest_pattern.search(f.LocalPath())):
2959 # We expect all actual service manifest files to contain at least one
2960 # qualified reference to service_manager::Manifest.
2961 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
Daniel Cheng13ca61a882017-08-25 15:11:252962 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172963 for pattern in file_patterns:
2964 if input_api.fnmatch.fnmatch(
2965 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042966 skip = False
2967 for exclude in exclude_paths:
2968 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2969 skip = True
2970 break
2971 if skip:
2972 continue
Daniel Cheng13ca61a882017-08-25 15:11:252973 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172974 break
2975
Daniel Cheng7052cdf2017-11-21 19:23:292976 return to_check
2977
2978
2979def _CheckIpcOwners(input_api, output_api):
2980 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2981 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2982
2983 if to_check:
2984 # If there are any OWNERS files to check, there are IPC-related changes in
2985 # this CL. Auto-CC the review list.
2986 output_api.AppendCC('[email protected]')
2987
2988 # Go through the OWNERS files to check, filtering out rules that are already
2989 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172990 for owners_file, patterns in to_check.iteritems():
2991 try:
2992 with file(owners_file) as f:
2993 lines = set(f.read().splitlines())
2994 for entry in patterns.itervalues():
2995 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2996 ]
2997 except IOError:
2998 # No OWNERS file, so all the rules are definitely missing.
2999 continue
3000
3001 # All the remaining lines weren't found in OWNERS files, so emit an error.
3002 errors = []
3003 for owners_file, patterns in to_check.iteritems():
3004 missing_lines = []
3005 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503006 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173007 missing_lines.extend(entry['rules'])
3008 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3009 if missing_lines:
3010 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053011 'Because of the presence of files:\n%s\n\n'
3012 '%s needs the following %d lines added:\n\n%s' %
3013 ('\n'.join(files), owners_file, len(missing_lines),
3014 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173015
3016 results = []
3017 if errors:
vabrf5ce3bf92016-07-11 14:52:413018 if input_api.is_committing:
3019 output = output_api.PresubmitError
3020 else:
3021 output = output_api.PresubmitPromptWarning
3022 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593023 'Found OWNERS files that need to be updated for IPC security ' +
3024 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173025 long_text='\n\n'.join(errors)))
3026
3027 return results
3028
3029
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263030def _CheckSetNoParent(input_api, output_api):
3031 """Checks that set noparent is only used together with an OWNERS file in
3032 //build/OWNERS.setnoparent (see also
3033 //docs/code_reviews.md#owners-files-details)
3034 """
3035 errors = []
3036
3037 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3038 allowed_owners_files = set()
3039 with open(allowed_owners_files_file, 'r') as f:
3040 for line in f:
3041 line = line.strip()
3042 if not line or line.startswith('#'):
3043 continue
3044 allowed_owners_files.add(line)
3045
3046 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3047
3048 for f in input_api.AffectedFiles(include_deletes=False):
3049 if not f.LocalPath().endswith('OWNERS'):
3050 continue
3051
3052 found_owners_files = set()
3053 found_set_noparent_lines = dict()
3054
3055 # Parse the OWNERS file.
3056 for lineno, line in enumerate(f.NewContents(), 1):
3057 line = line.strip()
3058 if line.startswith('set noparent'):
3059 found_set_noparent_lines[''] = lineno
3060 if line.startswith('file://'):
3061 if line in allowed_owners_files:
3062 found_owners_files.add('')
3063 if line.startswith('per-file'):
3064 match = per_file_pattern.match(line)
3065 if match:
3066 glob = match.group(1).strip()
3067 directive = match.group(2).strip()
3068 if directive == 'set noparent':
3069 found_set_noparent_lines[glob] = lineno
3070 if directive.startswith('file://'):
3071 if directive in allowed_owners_files:
3072 found_owners_files.add(glob)
3073
3074 # Check that every set noparent line has a corresponding file:// line
3075 # listed in build/OWNERS.setnoparent.
3076 for set_noparent_line in found_set_noparent_lines:
3077 if set_noparent_line in found_owners_files:
3078 continue
3079 errors.append(' %s:%d' % (f.LocalPath(),
3080 found_set_noparent_lines[set_noparent_line]))
3081
3082 results = []
3083 if errors:
3084 if input_api.is_committing:
3085 output = output_api.PresubmitError
3086 else:
3087 output = output_api.PresubmitPromptWarning
3088 results.append(output(
3089 'Found the following "set noparent" restrictions in OWNERS files that '
3090 'do not include owners from build/OWNERS.setnoparent:',
3091 long_text='\n\n'.join(errors)))
3092 return results
3093
3094
jbriance9e12f162016-11-25 07:57:503095def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313096 """Checks that added or removed lines in non third party affected
3097 header files do not lead to new useless class or struct forward
3098 declaration.
jbriance9e12f162016-11-25 07:57:503099 """
3100 results = []
3101 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3102 input_api.re.MULTILINE)
3103 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3104 input_api.re.MULTILINE)
3105 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313106 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193107 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493108 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313109 continue
3110
jbriance9e12f162016-11-25 07:57:503111 if not f.LocalPath().endswith('.h'):
3112 continue
3113
3114 contents = input_api.ReadFile(f)
3115 fwd_decls = input_api.re.findall(class_pattern, contents)
3116 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3117
3118 useless_fwd_decls = []
3119 for decl in fwd_decls:
3120 count = sum(1 for _ in input_api.re.finditer(
3121 r'\b%s\b' % input_api.re.escape(decl), contents))
3122 if count == 1:
3123 useless_fwd_decls.append(decl)
3124
3125 if not useless_fwd_decls:
3126 continue
3127
3128 for line in f.GenerateScmDiff().splitlines():
3129 if (line.startswith('-') and not line.startswith('--') or
3130 line.startswith('+') and not line.startswith('++')):
3131 for decl in useless_fwd_decls:
3132 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3133 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243134 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503135 (f.LocalPath(), decl)))
3136 useless_fwd_decls.remove(decl)
3137
3138 return results
3139
Jinsong Fan91ebbbd2019-04-16 14:57:173140def _CheckAndroidDebuggableBuild(input_api, output_api):
3141 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3142 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3143 this is a debuggable build of Android.
3144 """
3145 build_type_check_pattern = input_api.re.compile(
3146 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3147
3148 errors = []
3149
3150 sources = lambda affected_file: input_api.FilterSourceFile(
3151 affected_file,
3152 black_list=(_EXCLUDED_PATHS +
3153 _TEST_CODE_EXCLUDED_PATHS +
3154 input_api.DEFAULT_BLACK_LIST +
3155 (r"^android_webview[\\/]support_library[\\/]"
3156 "boundary_interfaces[\\/]",
3157 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3158 r'^third_party[\\/].*',
3159 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3160 r"webview[\\/]chromium[\\/]License.*",)),
3161 white_list=[r'.*\.java$'])
3162
3163 for f in input_api.AffectedSourceFiles(sources):
3164 for line_num, line in f.ChangedContents():
3165 if build_type_check_pattern.search(line):
3166 errors.append("%s:%d" % (f.LocalPath(), line_num))
3167
3168 results = []
3169
3170 if errors:
3171 results.append(output_api.PresubmitPromptWarning(
3172 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3173 ' Please use BuildInfo.isDebugAndroid() instead.',
3174 errors))
3175
3176 return results
jbriance9e12f162016-11-25 07:57:503177
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493178# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293179def _CheckAndroidToastUsage(input_api, output_api):
3180 """Checks that code uses org.chromium.ui.widget.Toast instead of
3181 android.widget.Toast (Chromium Toast doesn't force hardware
3182 acceleration on low-end devices, saving memory).
3183 """
3184 toast_import_pattern = input_api.re.compile(
3185 r'^import android\.widget\.Toast;$')
3186
3187 errors = []
3188
3189 sources = lambda affected_file: input_api.FilterSourceFile(
3190 affected_file,
3191 black_list=(_EXCLUDED_PATHS +
3192 _TEST_CODE_EXCLUDED_PATHS +
3193 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043194 (r'^chromecast[\\/].*',
3195 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493196 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293197
3198 for f in input_api.AffectedSourceFiles(sources):
3199 for line_num, line in f.ChangedContents():
3200 if toast_import_pattern.search(line):
3201 errors.append("%s:%d" % (f.LocalPath(), line_num))
3202
3203 results = []
3204
3205 if errors:
3206 results.append(output_api.PresubmitError(
3207 'android.widget.Toast usage is detected. Android toasts use hardware'
3208 ' acceleration, and can be\ncostly on low-end devices. Please use'
3209 ' org.chromium.ui.widget.Toast instead.\n'
3210 'Contact [email protected] if you have any questions.',
3211 errors))
3212
3213 return results
3214
3215
dgnaa68d5e2015-06-10 10:08:223216def _CheckAndroidCrLogUsage(input_api, output_api):
3217 """Checks that new logs using org.chromium.base.Log:
3218 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513219 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223220 """
pkotwicza1dd0b002016-05-16 14:41:043221
torne89540622017-03-24 19:41:303222 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043223 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303224 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043225 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303226 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043227 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3228 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093229 # The customtabs_benchmark is a small app that does not depend on Chromium
3230 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043231 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043232 ]
3233
dgnaa68d5e2015-06-10 10:08:223234 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123235 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3236 class_in_base_pattern = input_api.re.compile(
3237 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3238 has_some_log_import_pattern = input_api.re.compile(
3239 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223240 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
Tomasz Śniatowski3ae2f102020-03-23 15:35:553241 log_call_pattern = input_api.re.compile(r'\bLog\.\w\((?P<tag>\"?\w+)')
dgnaa68d5e2015-06-10 10:08:223242 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463243 r'static final String TAG = "(?P<name>(.*))"')
Tomasz Śniatowski3ae2f102020-03-23 15:35:553244 rough_log_decl_pattern = input_api.re.compile(r'\bString TAG\s*=')
dgnaa68d5e2015-06-10 10:08:223245
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463246 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493247 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043248 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123249
dgnaa68d5e2015-06-10 10:08:223250 tag_decl_errors = []
3251 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123252 tag_errors = []
dgn38736db2015-09-18 19:20:513253 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123254 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223255
3256 for f in input_api.AffectedSourceFiles(sources):
3257 file_content = input_api.ReadFile(f)
3258 has_modified_logs = False
dgnaa68d5e2015-06-10 10:08:223259 # Per line checks
dgn87d9fb62015-06-12 09:15:123260 if (cr_log_import_pattern.search(file_content) or
3261 (class_in_base_pattern.search(file_content) and
3262 not has_some_log_import_pattern.search(file_content))):
3263 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223264 for line_num, line in f.ChangedContents():
Tomasz Śniatowski3ae2f102020-03-23 15:35:553265 if rough_log_decl_pattern.search(line):
3266 has_modified_logs = True
dgnaa68d5e2015-06-10 10:08:223267
3268 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123269 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223270 if match:
3271 has_modified_logs = True
3272
3273 # Make sure it uses "TAG"
3274 if not match.group('tag') == 'TAG':
3275 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123276 else:
3277 # Report non cr Log function calls in changed lines
3278 for line_num, line in f.ChangedContents():
3279 if log_call_pattern.search(line):
3280 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223281
3282 # Per file checks
3283 if has_modified_logs:
3284 # Make sure the tag is using the "cr" prefix and is not too long
3285 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513286 tag_name = match.group('name') if match else None
3287 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223288 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513289 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223290 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513291 elif '.' in tag_name:
3292 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223293
3294 results = []
3295 if tag_decl_errors:
3296 results.append(output_api.PresubmitPromptWarning(
3297 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513298 '"private static final String TAG = "<package tag>".\n'
3299 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223300 tag_decl_errors))
3301
3302 if tag_length_errors:
3303 results.append(output_api.PresubmitError(
3304 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513305 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223306 tag_length_errors))
3307
3308 if tag_errors:
3309 results.append(output_api.PresubmitPromptWarning(
3310 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3311 tag_errors))
3312
dgn87d9fb62015-06-12 09:15:123313 if util_log_errors:
dgn4401aa52015-04-29 16:26:173314 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123315 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3316 util_log_errors))
3317
dgn38736db2015-09-18 19:20:513318 if tag_with_dot_errors:
3319 results.append(output_api.PresubmitPromptWarning(
3320 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3321 tag_with_dot_errors))
3322
dgn4401aa52015-04-29 16:26:173323 return results
3324
3325
Yoland Yanb92fa522017-08-28 17:37:063326def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3327 """Checks that junit.framework.* is no longer used."""
3328 deprecated_junit_framework_pattern = input_api.re.compile(
3329 r'^import junit\.framework\..*;',
3330 input_api.re.MULTILINE)
3331 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493332 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063333 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133334 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063335 for line_num, line in f.ChangedContents():
3336 if deprecated_junit_framework_pattern.search(line):
3337 errors.append("%s:%d" % (f.LocalPath(), line_num))
3338
3339 results = []
3340 if errors:
3341 results.append(output_api.PresubmitError(
3342 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3343 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3344 ' if you have any question.', errors))
3345 return results
3346
3347
3348def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3349 """Checks that if new Java test classes have inheritance.
3350 Either the new test class is JUnit3 test or it is a JUnit4 test class
3351 with a base class, either case is undesirable.
3352 """
3353 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3354
3355 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493356 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063357 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133358 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063359 if not f.OldContents():
3360 class_declaration_start_flag = False
3361 for line_num, line in f.ChangedContents():
3362 if class_declaration_pattern.search(line):
3363 class_declaration_start_flag = True
3364 if class_declaration_start_flag and ' extends ' in line:
3365 errors.append('%s:%d' % (f.LocalPath(), line_num))
3366 if '{' in line:
3367 class_declaration_start_flag = False
3368
3369 results = []
3370 if errors:
3371 results.append(output_api.PresubmitPromptWarning(
3372 'The newly created files include Test classes that inherits from base'
3373 ' class. Please do not use inheritance in JUnit4 tests or add new'
3374 ' JUnit3 tests. Contact [email protected] if you have any'
3375 ' questions.', errors))
3376 return results
3377
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203378
yolandyan45001472016-12-21 21:12:423379def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3380 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3381 deprecated_annotation_import_pattern = input_api.re.compile(
3382 r'^import android\.test\.suitebuilder\.annotation\..*;',
3383 input_api.re.MULTILINE)
3384 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493385 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423386 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133387 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423388 for line_num, line in f.ChangedContents():
3389 if deprecated_annotation_import_pattern.search(line):
3390 errors.append("%s:%d" % (f.LocalPath(), line_num))
3391
3392 results = []
3393 if errors:
3394 results.append(output_api.PresubmitError(
3395 'Annotations in android.test.suitebuilder.annotation have been'
3396 ' deprecated since API level 24. Please use android.support.test.filters'
3397 ' from //third_party/android_support_test_runner:runner_java instead.'
3398 ' Contact [email protected] if you have any questions.', errors))
3399 return results
3400
3401
agrieve7b6479d82015-10-07 14:24:223402def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3403 """Checks if MDPI assets are placed in a correct directory."""
3404 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3405 ('/res/drawable/' in f.LocalPath() or
3406 '/res/drawable-ldrtl/' in f.LocalPath()))
3407 errors = []
3408 for f in input_api.AffectedFiles(include_deletes=False,
3409 file_filter=file_filter):
3410 errors.append(' %s' % f.LocalPath())
3411
3412 results = []
3413 if errors:
3414 results.append(output_api.PresubmitError(
3415 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3416 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3417 '/res/drawable-ldrtl/.\n'
3418 'Contact [email protected] if you have questions.', errors))
3419 return results
3420
3421
Nate Fischer535972b2017-09-16 01:06:183422def _CheckAndroidWebkitImports(input_api, output_api):
3423 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353424 android.webview.ValueCallback except in the WebView glue layer
3425 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183426 """
3427 valuecallback_import_pattern = input_api.re.compile(
3428 r'^import android\.webkit\.ValueCallback;$')
3429
3430 errors = []
3431
3432 sources = lambda affected_file: input_api.FilterSourceFile(
3433 affected_file,
3434 black_list=(_EXCLUDED_PATHS +
3435 _TEST_CODE_EXCLUDED_PATHS +
3436 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353437 (r'^android_webview[\\/]glue[\\/].*',
3438 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493439 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183440
3441 for f in input_api.AffectedSourceFiles(sources):
3442 for line_num, line in f.ChangedContents():
3443 if valuecallback_import_pattern.search(line):
3444 errors.append("%s:%d" % (f.LocalPath(), line_num))
3445
3446 results = []
3447
3448 if errors:
3449 results.append(output_api.PresubmitError(
3450 'android.webkit.ValueCallback usage is detected outside of the glue'
3451 ' layer. To stay compatible with the support library, android.webkit.*'
3452 ' classes should only be used inside the glue layer and'
3453 ' org.chromium.base.Callback should be used instead.',
3454 errors))
3455
3456 return results
3457
3458
Becky Zhou7c69b50992018-12-10 19:37:573459def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3460 """Checks Android XML styles """
3461 import sys
3462 original_sys_path = sys.path
3463 try:
3464 sys.path = sys.path + [input_api.os_path.join(
3465 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3466 import checkxmlstyle
3467 finally:
3468 # Restore sys.path to what it was before.
3469 sys.path = original_sys_path
3470
3471 if is_check_on_upload:
3472 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3473 else:
3474 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3475
3476
agrievef32bcc72016-04-04 14:57:403477class PydepsChecker(object):
3478 def __init__(self, input_api, pydeps_files):
3479 self._file_cache = {}
3480 self._input_api = input_api
3481 self._pydeps_files = pydeps_files
3482
3483 def _LoadFile(self, path):
3484 """Returns the list of paths within a .pydeps file relative to //."""
3485 if path not in self._file_cache:
3486 with open(path) as f:
3487 self._file_cache[path] = f.read()
3488 return self._file_cache[path]
3489
3490 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3491 """Returns an interable of paths within the .pydep, relativized to //."""
3492 os_path = self._input_api.os_path
3493 pydeps_dir = os_path.dirname(pydeps_path)
3494 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3495 if not l.startswith('*'))
3496 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3497
3498 def _CreateFilesToPydepsMap(self):
3499 """Returns a map of local_path -> list_of_pydeps."""
3500 ret = {}
3501 for pydep_local_path in self._pydeps_files:
3502 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3503 ret.setdefault(path, []).append(pydep_local_path)
3504 return ret
3505
3506 def ComputeAffectedPydeps(self):
3507 """Returns an iterable of .pydeps files that might need regenerating."""
3508 affected_pydeps = set()
3509 file_to_pydeps_map = None
3510 for f in self._input_api.AffectedFiles(include_deletes=True):
3511 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463512 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3513 # subrepositories. We can't figure out which files change, so re-check
3514 # all files.
3515 # Changes to print_python_deps.py affect all .pydeps.
3516 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403517 return self._pydeps_files
3518 elif local_path.endswith('.pydeps'):
3519 if local_path in self._pydeps_files:
3520 affected_pydeps.add(local_path)
3521 elif local_path.endswith('.py'):
3522 if file_to_pydeps_map is None:
3523 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3524 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3525 return affected_pydeps
3526
3527 def DetermineIfStale(self, pydeps_path):
3528 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413529 import difflib
John Budorick47ca3fe2018-02-10 00:53:103530 import os
3531
agrievef32bcc72016-04-04 14:57:403532 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3533 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103534 env = dict(os.environ)
3535 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403536 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103537 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413538 old_contents = old_pydeps_data[2:]
3539 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403540 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413541 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403542
3543
Tibor Goldschwendt360793f72019-06-25 18:23:493544def _ParseGclientArgs():
3545 args = {}
3546 with open('build/config/gclient_args.gni', 'r') as f:
3547 for line in f:
3548 line = line.strip()
3549 if not line or line.startswith('#'):
3550 continue
3551 attribute, value = line.split('=')
3552 args[attribute.strip()] = value.strip()
3553 return args
3554
3555
agrievef32bcc72016-04-04 14:57:403556def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3557 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403558 # This check is for Python dependency lists (.pydeps files), and involves
3559 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3560 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283561 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003562 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493563 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403564 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3565 results = []
3566 # First, check for new / deleted .pydeps.
3567 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033568 # Check whether we are running the presubmit check for a file in src.
3569 # f.LocalPath is relative to repo (src, or internal repo).
3570 # os_path.exists is relative to src repo.
3571 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3572 # to src and we can conclude that the pydeps is in src.
3573 if input_api.os_path.exists(f.LocalPath()):
3574 if f.LocalPath().endswith('.pydeps'):
3575 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3576 results.append(output_api.PresubmitError(
3577 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3578 'remove %s' % f.LocalPath()))
3579 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3580 results.append(output_api.PresubmitError(
3581 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3582 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403583
3584 if results:
3585 return results
3586
3587 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3588
3589 for pydep_path in checker.ComputeAffectedPydeps():
3590 try:
phajdan.jr0d9878552016-11-04 10:49:413591 result = checker.DetermineIfStale(pydep_path)
3592 if result:
3593 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403594 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413595 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3596 'To regenerate, run:\n\n %s' %
3597 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403598 except input_api.subprocess.CalledProcessError as error:
3599 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3600 long_text=error.output)]
3601
3602 return results
3603
3604
glidere61efad2015-02-18 17:39:433605def _CheckSingletonInHeaders(input_api, output_api):
3606 """Checks to make sure no header files have |Singleton<|."""
3607 def FileFilter(affected_file):
3608 # It's ok for base/memory/singleton.h to have |Singleton<|.
3609 black_list = (_EXCLUDED_PATHS +
3610 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043611 (r"^base[\\/]memory[\\/]singleton\.h$",
3612 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473613 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433614 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3615
sergeyu34d21222015-09-16 00:11:443616 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433617 files = []
3618 for f in input_api.AffectedSourceFiles(FileFilter):
3619 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3620 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3621 contents = input_api.ReadFile(f)
3622 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243623 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433624 pattern.search(line)):
3625 files.append(f)
3626 break
3627
3628 if files:
yolandyandaabc6d2016-04-18 18:29:393629 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443630 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433631 'Please move them to an appropriate source file so that the ' +
3632 'template gets instantiated in a single compilation unit.',
3633 files) ]
3634 return []
3635
3636
[email protected]fd20b902014-05-09 02:14:533637_DEPRECATED_CSS = [
3638 # Values
3639 ( "-webkit-box", "flex" ),
3640 ( "-webkit-inline-box", "inline-flex" ),
3641 ( "-webkit-flex", "flex" ),
3642 ( "-webkit-inline-flex", "inline-flex" ),
3643 ( "-webkit-min-content", "min-content" ),
3644 ( "-webkit-max-content", "max-content" ),
3645
3646 # Properties
3647 ( "-webkit-background-clip", "background-clip" ),
3648 ( "-webkit-background-origin", "background-origin" ),
3649 ( "-webkit-background-size", "background-size" ),
3650 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443651 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533652
3653 # Functions
3654 ( "-webkit-gradient", "gradient" ),
3655 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3656 ( "-webkit-linear-gradient", "linear-gradient" ),
3657 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3658 ( "-webkit-radial-gradient", "radial-gradient" ),
3659 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3660]
3661
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203662
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493663# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243664def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533665 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253666 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343667 documentation and iOS CSS for dom distiller
3668 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253669 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533670 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493671 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253672 black_list = (_EXCLUDED_PATHS +
3673 _TEST_CODE_EXCLUDED_PATHS +
3674 input_api.DEFAULT_BLACK_LIST +
3675 (r"^chrome/common/extensions/docs",
3676 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343677 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443678 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253679 r"^native_client_sdk"))
3680 file_filter = lambda f: input_api.FilterSourceFile(
3681 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533682 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3683 for line_num, line in fpath.ChangedContents():
3684 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023685 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533686 results.append(output_api.PresubmitError(
3687 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3688 (fpath.LocalPath(), line_num, deprecated_value, value)))
3689 return results
3690
mohan.reddyf21db962014-10-16 12:26:473691
rlanday6802cf632017-05-30 17:48:363692def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363693 bad_files = {}
3694 for f in input_api.AffectedFiles(include_deletes=False):
3695 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493696 not f.LocalPath().startswith('third_party/blink') and
3697 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363698 continue
3699
Daniel Bratell65b033262019-04-23 08:17:063700 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363701 continue
3702
Vaclav Brozekd5de76a2018-03-17 07:57:503703 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363704 if "#include" in line and "../" in line]
3705 if not relative_includes:
3706 continue
3707 bad_files[f.LocalPath()] = relative_includes
3708
3709 if not bad_files:
3710 return []
3711
3712 error_descriptions = []
3713 for file_path, bad_lines in bad_files.iteritems():
3714 error_description = file_path
3715 for line in bad_lines:
3716 error_description += '\n ' + line
3717 error_descriptions.append(error_description)
3718
3719 results = []
3720 results.append(output_api.PresubmitError(
3721 'You added one or more relative #include paths (including "../").\n'
3722 'These shouldn\'t be used because they can be used to include headers\n'
3723 'from code that\'s not correctly specified as a dependency in the\n'
3724 'relevant BUILD.gn file(s).',
3725 error_descriptions))
3726
3727 return results
3728
Takeshi Yoshinoe387aa32017-08-02 13:16:133729
Daniel Bratell65b033262019-04-23 08:17:063730def _CheckForCcIncludes(input_api, output_api):
3731 """Check that nobody tries to include a cc file. It's a relatively
3732 common error which results in duplicate symbols in object
3733 files. This may not always break the build until someone later gets
3734 very confusing linking errors."""
3735 results = []
3736 for f in input_api.AffectedFiles(include_deletes=False):
3737 # We let third_party code do whatever it wants
3738 if (f.LocalPath().startswith('third_party') and
3739 not f.LocalPath().startswith('third_party/blink') and
3740 not f.LocalPath().startswith('third_party\\blink')):
3741 continue
3742
3743 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3744 continue
3745
3746 for _, line in f.ChangedContents():
3747 if line.startswith('#include "'):
3748 included_file = line.split('"')[1]
3749 if _IsCPlusPlusFile(input_api, included_file):
3750 # The most common naming for external files with C++ code,
3751 # apart from standard headers, is to call them foo.inc, but
3752 # Chromium sometimes uses foo-inc.cc so allow that as well.
3753 if not included_file.endswith(('.h', '-inc.cc')):
3754 results.append(output_api.PresubmitError(
3755 'Only header files or .inc files should be included in other\n'
3756 'C++ files. Compiling the contents of a cc file more than once\n'
3757 'will cause duplicate information in the build which may later\n'
3758 'result in strange link_errors.\n' +
3759 f.LocalPath() + ':\n ' +
3760 line))
3761
3762 return results
3763
3764
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203765def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3766 if not isinstance(key, ast.Str):
3767 return 'Key at line %d must be a string literal' % key.lineno
3768 if not isinstance(value, ast.Dict):
3769 return 'Value at line %d must be a dict' % value.lineno
3770 if len(value.keys) != 1:
3771 return 'Dict at line %d must have single entry' % value.lineno
3772 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3773 return (
3774 'Entry at line %d must have a string literal \'filepath\' as key' %
3775 value.lineno)
3776 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133777
Takeshi Yoshinoe387aa32017-08-02 13:16:133778
Sergey Ulanov4af16052018-11-08 02:41:463779def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203780 if not isinstance(key, ast.Str):
3781 return 'Key at line %d must be a string literal' % key.lineno
3782 if not isinstance(value, ast.List):
3783 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463784 for element in value.elts:
3785 if not isinstance(element, ast.Str):
3786 return 'Watchlist elements on line %d is not a string' % key.lineno
3787 if not email_regex.match(element.s):
3788 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3789 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203790 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133791
Takeshi Yoshinoe387aa32017-08-02 13:16:133792
Sergey Ulanov4af16052018-11-08 02:41:463793def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203794 mismatch_template = (
3795 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3796 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133797
Sergey Ulanov4af16052018-11-08 02:41:463798 email_regex = input_api.re.compile(
3799 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3800
3801 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203802 i = 0
3803 last_key = ''
3804 while True:
3805 if i >= len(wd_dict.keys):
3806 if i >= len(w_dict.keys):
3807 return None
3808 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3809 elif i >= len(w_dict.keys):
3810 return (
3811 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133812
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203813 wd_key = wd_dict.keys[i]
3814 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133815
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203816 result = _CheckWatchlistDefinitionsEntrySyntax(
3817 wd_key, wd_dict.values[i], ast)
3818 if result is not None:
3819 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133820
Sergey Ulanov4af16052018-11-08 02:41:463821 result = _CheckWatchlistsEntrySyntax(
3822 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203823 if result is not None:
3824 return 'Bad entry in WATCHLISTS dict: %s' % result
3825
3826 if wd_key.s != w_key.s:
3827 return mismatch_template % (
3828 '%s at line %d' % (wd_key.s, wd_key.lineno),
3829 '%s at line %d' % (w_key.s, w_key.lineno))
3830
3831 if wd_key.s < last_key:
3832 return (
3833 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3834 (wd_key.lineno, w_key.lineno))
3835 last_key = wd_key.s
3836
3837 i = i + 1
3838
3839
Sergey Ulanov4af16052018-11-08 02:41:463840def _CheckWATCHLISTSSyntax(expression, input_api):
3841 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203842 if not isinstance(expression, ast.Expression):
3843 return 'WATCHLISTS file must contain a valid expression'
3844 dictionary = expression.body
3845 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3846 return 'WATCHLISTS file must have single dict with exactly two entries'
3847
3848 first_key = dictionary.keys[0]
3849 first_value = dictionary.values[0]
3850 second_key = dictionary.keys[1]
3851 second_value = dictionary.values[1]
3852
3853 if (not isinstance(first_key, ast.Str) or
3854 first_key.s != 'WATCHLIST_DEFINITIONS' or
3855 not isinstance(first_value, ast.Dict)):
3856 return (
3857 'The first entry of the dict in WATCHLISTS file must be '
3858 'WATCHLIST_DEFINITIONS dict')
3859
3860 if (not isinstance(second_key, ast.Str) or
3861 second_key.s != 'WATCHLISTS' or
3862 not isinstance(second_value, ast.Dict)):
3863 return (
3864 'The second entry of the dict in WATCHLISTS file must be '
3865 'WATCHLISTS dict')
3866
Sergey Ulanov4af16052018-11-08 02:41:463867 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133868
3869
3870def _CheckWATCHLISTS(input_api, output_api):
3871 for f in input_api.AffectedFiles(include_deletes=False):
3872 if f.LocalPath() == 'WATCHLISTS':
3873 contents = input_api.ReadFile(f, 'r')
3874
3875 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203876 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133877 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203878 # Get an AST tree for it and scan the tree for detailed style checking.
3879 expression = input_api.ast.parse(
3880 contents, filename='WATCHLISTS', mode='eval')
3881 except ValueError as e:
3882 return [output_api.PresubmitError(
3883 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3884 except SyntaxError as e:
3885 return [output_api.PresubmitError(
3886 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3887 except TypeError as e:
3888 return [output_api.PresubmitError(
3889 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133890
Sergey Ulanov4af16052018-11-08 02:41:463891 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203892 if result is not None:
3893 return [output_api.PresubmitError(result)]
3894 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133895
3896 return []
3897
3898
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193899def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3900 """Checks that newly added header files have corresponding GN changes.
3901 Note that this is only a heuristic. To be precise, run script:
3902 build/check_gn_headers.py.
3903 """
3904
3905 def headers(f):
3906 return input_api.FilterSourceFile(
3907 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3908
3909 new_headers = []
3910 for f in input_api.AffectedSourceFiles(headers):
3911 if f.Action() != 'A':
3912 continue
3913 new_headers.append(f.LocalPath())
3914
3915 def gn_files(f):
3916 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3917
3918 all_gn_changed_contents = ''
3919 for f in input_api.AffectedSourceFiles(gn_files):
3920 for _, line in f.ChangedContents():
3921 all_gn_changed_contents += line
3922
3923 problems = []
3924 for header in new_headers:
3925 basename = input_api.os_path.basename(header)
3926 if basename not in all_gn_changed_contents:
3927 problems.append(header)
3928
3929 if problems:
3930 return [output_api.PresubmitPromptWarning(
3931 'Missing GN changes for new header files', items=sorted(problems),
3932 long_text='Please double check whether newly added header files need '
3933 'corresponding changes in gn or gni files.\nThis checking is only a '
3934 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3935 'Read https://crbug.com/661774 for more info.')]
3936 return []
3937
3938
Michael Giuffridad3bc8672018-10-25 22:48:023939def _CheckCorrectProductNameInMessages(input_api, output_api):
3940 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3941
3942 This assumes we won't intentionally reference one product from the other
3943 product.
3944 """
3945 all_problems = []
3946 test_cases = [{
3947 "filename_postfix": "google_chrome_strings.grd",
3948 "correct_name": "Chrome",
3949 "incorrect_name": "Chromium",
3950 }, {
3951 "filename_postfix": "chromium_strings.grd",
3952 "correct_name": "Chromium",
3953 "incorrect_name": "Chrome",
3954 }]
3955
3956 for test_case in test_cases:
3957 problems = []
3958 filename_filter = lambda x: x.LocalPath().endswith(
3959 test_case["filename_postfix"])
3960
3961 # Check each new line. Can yield false positives in multiline comments, but
3962 # easier than trying to parse the XML because messages can have nested
3963 # children, and associating message elements with affected lines is hard.
3964 for f in input_api.AffectedSourceFiles(filename_filter):
3965 for line_num, line in f.ChangedContents():
3966 if "<message" in line or "<!--" in line or "-->" in line:
3967 continue
3968 if test_case["incorrect_name"] in line:
3969 problems.append(
3970 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3971
3972 if problems:
3973 message = (
3974 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3975 % (test_case["correct_name"], test_case["correct_name"],
3976 test_case["incorrect_name"]))
3977 all_problems.append(
3978 output_api.PresubmitPromptWarning(message, items=problems))
3979
3980 return all_problems
3981
3982
Dirk Pranke3c18a382019-03-15 01:07:513983def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3984 # TODO(crbug.com/941824): We need to make sure the entries in
3985 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3986 # so that users of //buildtools in other projects get the same tooling
3987 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3988 # support to gclient, we can eliminate the duplication and delete
3989 # this presubmit check.
3990
3991 # Update this regexp if new revisions are added to the files.
3992 rev_regexp = input_api.re.compile(
Xiaohui Chen3fdc6742020-02-29 02:13:263993 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513994
3995 # If a user is changing one revision, they need to change the same
3996 # line in both files. This means that any given change should contain
3997 # exactly the same list of changed lines that match the regexps. The
3998 # replace(' ', '') call allows us to ignore whitespace changes to the
3999 # lines. The 'long_text' parameter to the error will contain the
4000 # list of changed lines in both files, which should make it easy enough
4001 # to spot the error without going overboard in this implementation.
4002 revs_changes = {
4003 'DEPS': {},
4004 'buildtools/DEPS': {},
4005 }
4006 long_text = ''
4007
4008 for f in input_api.AffectedFiles(
4009 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4010 for line_num, line in f.ChangedContents():
4011 if rev_regexp.search(line):
4012 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4013 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4014
4015 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4016 return [output_api.PresubmitError(
4017 'Change buildtools revisions in sync in both //DEPS and '
4018 '//buildtools/DEPS.', long_text=long_text + '\n')]
4019 else:
4020 return []
4021
4022
Daniel Bratell93eb6c62019-04-29 20:13:364023def _CheckForTooLargeFiles(input_api, output_api):
4024 """Avoid large files, especially binary files, in the repository since
4025 git doesn't scale well for those. They will be in everyone's repo
4026 clones forever, forever making Chromium slower to clone and work
4027 with."""
4028
4029 # Uploading files to cloud storage is not trivial so we don't want
4030 # to set the limit too low, but the upper limit for "normal" large
4031 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4032 # anything over 20 MB is exceptional.
4033 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4034
4035 too_large_files = []
4036 for f in input_api.AffectedFiles():
4037 # Check both added and modified files (but not deleted files).
4038 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384039 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364040 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4041 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4042
4043 if too_large_files:
4044 message = (
4045 'Do not commit large files to git since git scales badly for those.\n' +
4046 'Instead put the large files in cloud storage and use DEPS to\n' +
4047 'fetch them.\n' + '\n'.join(too_large_files)
4048 )
4049 return [output_api.PresubmitError(
4050 'Too large files found in commit', long_text=message + '\n')]
4051 else:
4052 return []
4053
Max Morozb47503b2019-08-08 21:03:274054
4055def _CheckFuzzTargets(input_api, output_api):
4056 """Checks specific for fuzz target sources."""
4057 EXPORTED_SYMBOLS = [
4058 'LLVMFuzzerInitialize',
4059 'LLVMFuzzerCustomMutator',
4060 'LLVMFuzzerCustomCrossOver',
4061 'LLVMFuzzerMutate',
4062 ]
4063
4064 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4065
4066 def FilterFile(affected_file):
4067 """Ignore libFuzzer source code."""
4068 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4069 black_list = r"^third_party[\\/]libFuzzer"
4070
4071 return input_api.FilterSourceFile(
4072 affected_file,
4073 white_list=[white_list],
4074 black_list=[black_list])
4075
4076 files_with_missing_header = []
4077 for f in input_api.AffectedSourceFiles(FilterFile):
4078 contents = input_api.ReadFile(f, 'r')
4079 if REQUIRED_HEADER in contents:
4080 continue
4081
4082 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4083 files_with_missing_header.append(f.LocalPath())
4084
4085 if not files_with_missing_header:
4086 return []
4087
4088 long_text = (
4089 'If you define any of the libFuzzer optional functions (%s), it is '
4090 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4091 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4092 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4093 'to access command line arguments passed to the fuzzer. Instead, prefer '
4094 'static initialization and shared resources as documented in '
4095 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4096 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4097 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4098 )
4099
4100 return [output_api.PresubmitPromptWarning(
4101 message="Missing '%s' in:" % REQUIRED_HEADER,
4102 items=files_with_missing_header,
4103 long_text=long_text)]
4104
4105
Mohamed Heikald048240a2019-11-12 16:57:374106def _CheckNewImagesWarning(input_api, output_api):
4107 """
4108 Warns authors who add images into the repo to make sure their images are
4109 optimized before committing.
4110 """
4111 images_added = False
4112 image_paths = []
4113 errors = []
4114 filter_lambda = lambda x: input_api.FilterSourceFile(
4115 x,
4116 black_list=(('(?i).*test', r'.*\/junit\/')
4117 + input_api.DEFAULT_BLACK_LIST),
4118 white_list=[r'.*\/(drawable|mipmap)' ]
4119 )
4120 for f in input_api.AffectedFiles(
4121 include_deletes=False, file_filter=filter_lambda):
4122 local_path = f.LocalPath().lower()
4123 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4124 images_added = True
4125 image_paths.append(f)
4126 if images_added:
4127 errors.append(output_api.PresubmitPromptWarning(
4128 'It looks like you are trying to commit some images. If these are '
4129 'non-test-only images, please make sure to read and apply the tips in '
4130 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4131 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4132 'FYI only and will not block your CL on the CQ.', image_paths))
4133 return errors
4134
4135
dgnaa68d5e2015-06-10 10:08:224136def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574137 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224138 results = []
dgnaa68d5e2015-06-10 10:08:224139 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174140 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224141 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294142 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064143 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4144 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424145 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184146 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574147 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374148 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154149 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574150 return results
4151
4152def _AndroidSpecificOnCommitChecks(input_api, output_api):
4153 """Groups commit checks that target android code."""
4154 results = []
4155 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224156 return results
4157
4158
[email protected]22c9bd72011-03-27 16:47:394159def _CommonChecks(input_api, output_api):
4160 """Checks common to both upload and commit."""
4161 results = []
4162 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384163 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544164 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084165
4166 author = input_api.change.author_email
4167 if author and author not in _KNOWN_ROBOTS:
4168 results.extend(
4169 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4170
[email protected]55459852011-08-10 15:17:194171 results.extend(
[email protected]760deea2013-12-10 19:33:494172 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234173 results.extend(
4174 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544175 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184176 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344177 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524178 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224179 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444180 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594181 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314182 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064183 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124184 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184185 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224186 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304187 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494188 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034189 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494190 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444191 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294192 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274193 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074194 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544195 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444196 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394197 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554198 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044199 results.extend(
4200 input_api.canned_checks.CheckChangeHasNoTabs(
4201 input_api,
4202 output_api,
4203 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404204 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164205 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084206 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244207 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474208 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044209 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054210 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144211 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234212 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434213 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404214 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154215 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174216 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264217 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504218 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364219 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064220 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134221 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434222 results.extend(input_api.RunTests(
4223 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144224 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Mustafa Emre Acer51f2f742020-03-09 19:41:124225 results.extend(_CheckTranslationExpectations(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024226 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514227 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364228 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004229 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244230
Vaclav Brozekcdc7defb2018-03-20 09:54:354231 for f in input_api.AffectedFiles():
4232 path, name = input_api.os_path.split(f.LocalPath())
4233 if name == 'PRESUBMIT.py':
4234 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004235 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4236 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074237 # The PRESUBMIT.py file (and the directory containing it) might
4238 # have been affected by being moved or removed, so only try to
4239 # run the tests if they still exist.
4240 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4241 input_api, output_api, full_path,
4242 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394243 return results
[email protected]1f7b4172010-01-28 01:17:344244
[email protected]b337cb5b2011-01-23 21:24:054245
[email protected]b8079ae4a2012-12-05 19:56:494246def _CheckPatchFiles(input_api, output_api):
4247 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4248 if f.LocalPath().endswith(('.orig', '.rej'))]
4249 if problems:
4250 return [output_api.PresubmitError(
4251 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034252 else:
4253 return []
[email protected]b8079ae4a2012-12-05 19:56:494254
4255
Kent Tamura5a8755d2017-06-29 23:37:074256def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214257 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4258 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4259 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074260 include_re = input_api.re.compile(
4261 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4262 extension_re = input_api.re.compile(r'\.[a-z]+$')
4263 errors = []
4264 for f in input_api.AffectedFiles():
4265 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4266 continue
4267 found_line_number = None
4268 found_macro = None
4269 for line_num, line in f.ChangedContents():
4270 match = macro_re.search(line)
4271 if match:
4272 found_line_number = line_num
4273 found_macro = match.group(2)
4274 break
4275 if not found_line_number:
4276 continue
4277
4278 found_include = False
4279 for line in f.NewContents():
4280 if include_re.search(line):
4281 found_include = True
4282 break
4283 if found_include:
4284 continue
4285
4286 if not f.LocalPath().endswith('.h'):
4287 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4288 try:
4289 content = input_api.ReadFile(primary_header_path, 'r')
4290 if include_re.search(content):
4291 continue
4292 except IOError:
4293 pass
4294 errors.append('%s:%d %s macro is used without including build/'
4295 'build_config.h.'
4296 % (f.LocalPath(), found_line_number, found_macro))
4297 if errors:
4298 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4299 return []
4300
4301
[email protected]b00342e7f2013-03-26 16:21:544302def _DidYouMeanOSMacro(bad_macro):
4303 try:
4304 return {'A': 'OS_ANDROID',
4305 'B': 'OS_BSD',
4306 'C': 'OS_CHROMEOS',
4307 'F': 'OS_FREEBSD',
4308 'L': 'OS_LINUX',
4309 'M': 'OS_MACOSX',
4310 'N': 'OS_NACL',
4311 'O': 'OS_OPENBSD',
4312 'P': 'OS_POSIX',
4313 'S': 'OS_SOLARIS',
4314 'W': 'OS_WIN'}[bad_macro[3].upper()]
4315 except KeyError:
4316 return ''
4317
4318
4319def _CheckForInvalidOSMacrosInFile(input_api, f):
4320 """Check for sensible looking, totally invalid OS macros."""
4321 preprocessor_statement = input_api.re.compile(r'^\s*#')
4322 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4323 results = []
4324 for lnum, line in f.ChangedContents():
4325 if preprocessor_statement.search(line):
4326 for match in os_macro.finditer(line):
4327 if not match.group(1) in _VALID_OS_MACROS:
4328 good = _DidYouMeanOSMacro(match.group(1))
4329 did_you_mean = ' (did you mean %s?)' % good if good else ''
4330 results.append(' %s:%d %s%s' % (f.LocalPath(),
4331 lnum,
4332 match.group(1),
4333 did_you_mean))
4334 return results
4335
4336
4337def _CheckForInvalidOSMacros(input_api, output_api):
4338 """Check all affected files for invalid OS macros."""
4339 bad_macros = []
tzik3f295992018-12-04 20:32:234340 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474341 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544342 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4343
4344 if not bad_macros:
4345 return []
4346
4347 return [output_api.PresubmitError(
4348 'Possibly invalid OS macro[s] found. Please fix your code\n'
4349 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4350
lliabraa35bab3932014-10-01 12:16:444351
4352def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4353 """Check all affected files for invalid "if defined" macros."""
4354 ALWAYS_DEFINED_MACROS = (
4355 "TARGET_CPU_PPC",
4356 "TARGET_CPU_PPC64",
4357 "TARGET_CPU_68K",
4358 "TARGET_CPU_X86",
4359 "TARGET_CPU_ARM",
4360 "TARGET_CPU_MIPS",
4361 "TARGET_CPU_SPARC",
4362 "TARGET_CPU_ALPHA",
4363 "TARGET_IPHONE_SIMULATOR",
4364 "TARGET_OS_EMBEDDED",
4365 "TARGET_OS_IPHONE",
4366 "TARGET_OS_MAC",
4367 "TARGET_OS_UNIX",
4368 "TARGET_OS_WIN32",
4369 )
4370 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4371 results = []
4372 for lnum, line in f.ChangedContents():
4373 for match in ifdef_macro.finditer(line):
4374 if match.group(1) in ALWAYS_DEFINED_MACROS:
4375 always_defined = ' %s is always defined. ' % match.group(1)
4376 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4377 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4378 lnum,
4379 always_defined,
4380 did_you_mean))
4381 return results
4382
4383
4384def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4385 """Check all affected files for invalid "if defined" macros."""
4386 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054387 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444388 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054389 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214390 continue
lliabraa35bab3932014-10-01 12:16:444391 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4392 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4393
4394 if not bad_macros:
4395 return []
4396
4397 return [output_api.PresubmitError(
4398 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4399 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4400 bad_macros)]
4401
4402
mlamouria82272622014-09-16 18:45:044403def _CheckForIPCRules(input_api, output_api):
4404 """Check for same IPC rules described in
4405 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4406 """
4407 base_pattern = r'IPC_ENUM_TRAITS\('
4408 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4409 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4410
4411 problems = []
4412 for f in input_api.AffectedSourceFiles(None):
4413 local_path = f.LocalPath()
4414 if not local_path.endswith('.h'):
4415 continue
4416 for line_number, line in f.ChangedContents():
4417 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4418 problems.append(
4419 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4420
4421 if problems:
4422 return [output_api.PresubmitPromptWarning(
4423 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4424 else:
4425 return []
4426
[email protected]b00342e7f2013-03-26 16:21:544427
Stephen Martinis97a394142018-06-07 23:06:054428def _CheckForLongPathnames(input_api, output_api):
4429 """Check to make sure no files being submitted have long paths.
4430 This causes issues on Windows.
4431 """
4432 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194433 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054434 local_path = f.LocalPath()
4435 # Windows has a path limit of 260 characters. Limit path length to 200 so
4436 # that we have some extra for the prefix on dev machines and the bots.
4437 if len(local_path) > 200:
4438 problems.append(local_path)
4439
4440 if problems:
4441 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4442 else:
4443 return []
4444
4445
Daniel Bratell8ba52722018-03-02 16:06:144446def _CheckForIncludeGuards(input_api, output_api):
4447 """Check that header files have proper guards against multiple inclusion.
4448 If a file should not have such guards (and it probably should) then it
4449 should include the string "no-include-guard-because-multiply-included".
4450 """
Daniel Bratell6a75baef62018-06-04 10:04:454451 def is_chromium_header_file(f):
4452 # We only check header files under the control of the Chromium
4453 # project. That is, those outside third_party apart from
4454 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324455 # We also exclude *_message_generator.h headers as they use
4456 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454457 file_with_path = input_api.os_path.normpath(f.LocalPath())
4458 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324459 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454460 (not file_with_path.startswith('third_party') or
4461 file_with_path.startswith(
4462 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144463
4464 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344465 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144466
4467 errors = []
4468
Daniel Bratell6a75baef62018-06-04 10:04:454469 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144470 guard_name = None
4471 guard_line_number = None
4472 seen_guard_end = False
4473
4474 file_with_path = input_api.os_path.normpath(f.LocalPath())
4475 base_file_name = input_api.os_path.splitext(
4476 input_api.os_path.basename(file_with_path))[0]
4477 upper_base_file_name = base_file_name.upper()
4478
4479 expected_guard = replace_special_with_underscore(
4480 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144481
4482 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574483 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4484 # are too many (1000+) files with slight deviations from the
4485 # coding style. The most important part is that the include guard
4486 # is there, and that it's unique, not the name so this check is
4487 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144488 #
4489 # As code becomes more uniform, this could be made stricter.
4490
4491 guard_name_pattern_list = [
4492 # Anything with the right suffix (maybe with an extra _).
4493 r'\w+_H__?',
4494
Daniel Bratell39b5b062018-05-16 18:09:574495 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144496 r'\w+_h',
4497
4498 # Anything including the uppercase name of the file.
4499 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4500 upper_base_file_name)) + r'\w*',
4501 ]
4502 guard_name_pattern = '|'.join(guard_name_pattern_list)
4503 guard_pattern = input_api.re.compile(
4504 r'#ifndef\s+(' + guard_name_pattern + ')')
4505
4506 for line_number, line in enumerate(f.NewContents()):
4507 if 'no-include-guard-because-multiply-included' in line:
4508 guard_name = 'DUMMY' # To not trigger check outside the loop.
4509 break
4510
4511 if guard_name is None:
4512 match = guard_pattern.match(line)
4513 if match:
4514 guard_name = match.group(1)
4515 guard_line_number = line_number
4516
Daniel Bratell39b5b062018-05-16 18:09:574517 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454518 # don't match the chromium style guide, but new files should
4519 # get it right.
4520 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574521 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144522 errors.append(output_api.PresubmitPromptWarning(
4523 'Header using the wrong include guard name %s' % guard_name,
4524 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574525 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144526 else:
4527 # The line after #ifndef should have a #define of the same name.
4528 if line_number == guard_line_number + 1:
4529 expected_line = '#define %s' % guard_name
4530 if line != expected_line:
4531 errors.append(output_api.PresubmitPromptWarning(
4532 'Missing "%s" for include guard' % expected_line,
4533 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4534 'Expected: %r\nGot: %r' % (expected_line, line)))
4535
4536 if not seen_guard_end and line == '#endif // %s' % guard_name:
4537 seen_guard_end = True
4538 elif seen_guard_end:
4539 if line.strip() != '':
4540 errors.append(output_api.PresubmitPromptWarning(
4541 'Include guard %s not covering the whole file' % (
4542 guard_name), [f.LocalPath()]))
4543 break # Nothing else to check and enough to warn once.
4544
4545 if guard_name is None:
4546 errors.append(output_api.PresubmitPromptWarning(
4547 'Missing include guard %s' % expected_guard,
4548 [f.LocalPath()],
4549 'Missing include guard in %s\n'
4550 'Recommended name: %s\n'
4551 'This check can be disabled by having the string\n'
4552 'no-include-guard-because-multiply-included in the header.' %
4553 (f.LocalPath(), expected_guard)))
4554
4555 return errors
4556
4557
mostynbb639aca52015-01-07 20:31:234558def _CheckForWindowsLineEndings(input_api, output_api):
4559 """Check source code and known ascii text files for Windows style line
4560 endings.
4561 """
earthdok1b5e0ee2015-03-10 15:19:104562 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234563
4564 file_inclusion_pattern = (
4565 known_text_files,
4566 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4567 )
4568
mostynbb639aca52015-01-07 20:31:234569 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534570 source_file_filter = lambda f: input_api.FilterSourceFile(
4571 f, white_list=file_inclusion_pattern, black_list=None)
4572 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504573 include_file = False
4574 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234575 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504576 include_file = True
4577 if include_file:
4578 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234579
4580 if problems:
4581 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4582 'these files to contain Windows style line endings?\n' +
4583 '\n'.join(problems))]
4584
4585 return []
4586
4587
Vaclav Brozekd5de76a2018-03-17 07:57:504588def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134589 """Checks that all source files use SYSLOG properly."""
4590 syslog_files = []
4591 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564592 for line_number, line in f.ChangedContents():
4593 if 'SYSLOG' in line:
4594 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4595
pastarmovj89f7ee12016-09-20 14:58:134596 if syslog_files:
4597 return [output_api.PresubmitPromptWarning(
4598 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4599 ' calls.\nFiles to check:\n', items=syslog_files)]
4600 return []
4601
4602
[email protected]1f7b4172010-01-28 01:17:344603def CheckChangeOnUpload(input_api, output_api):
4604 results = []
4605 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474606 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284607 results.extend(
jam93a6ee792017-02-08 23:59:224608 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194609 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224610 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134611 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164612 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534613 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194614 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274615 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544616 return results
[email protected]ca8d1982009-02-19 16:33:124617
4618
[email protected]1bfb8322014-04-23 01:02:414619def GetTryServerMasterForBot(bot):
4620 """Returns the Try Server master for the given bot.
4621
[email protected]0bb112362014-07-26 04:38:324622 It tries to guess the master from the bot name, but may still fail
4623 and return None. There is no longer a default master.
4624 """
4625 # Potentially ambiguous bot names are listed explicitly.
4626 master_map = {
tandriie5587792016-07-14 00:34:504627 'chromium_presubmit': 'master.tryserver.chromium.linux',
4628 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414629 }
[email protected]0bb112362014-07-26 04:38:324630 master = master_map.get(bot)
4631 if not master:
wnwen4fbaab82016-05-25 12:54:364632 if 'android' in bot:
tandriie5587792016-07-14 00:34:504633 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364634 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504635 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324636 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504637 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324638 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504639 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324640 return master
[email protected]1bfb8322014-04-23 01:02:414641
4642
[email protected]ca8d1982009-02-19 16:33:124643def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544644 results = []
[email protected]1f7b4172010-01-28 01:17:344645 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574646 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544647 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274648 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344649 input_api,
4650 output_api,
[email protected]2fdd1f362013-01-16 03:56:034651 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274652
jam93a6ee792017-02-08 23:59:224653 results.extend(
4654 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544655 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4656 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384657 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4658 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414659 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4660 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544661 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144662
4663
4664def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144665 import os
4666 import sys
4667 from io import StringIO
4668
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144669 new_or_added_paths = set(f.LocalPath()
4670 for f in input_api.AffectedFiles()
4671 if (f.Action() == 'A' or f.Action() == 'M'))
4672 removed_paths = set(f.LocalPath()
4673 for f in input_api.AffectedFiles(include_deletes=True)
4674 if f.Action() == 'D')
4675
4676 affected_grds = [f for f in input_api.AffectedFiles()
4677 if (f.LocalPath().endswith('.grd') or
4678 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164679 if not affected_grds:
4680 return []
4681
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144682 affected_png_paths = [f.AbsoluteLocalPath()
4683 for f in input_api.AffectedFiles()
4684 if (f.LocalPath().endswith('.png'))]
4685
4686 # Check for screenshots. Developers can upload screenshots using
4687 # tools/translation/upload_screenshots.py which finds and uploads
4688 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4689 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4690 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4691 #
4692 # The logic here is as follows:
4693 #
4694 # - If the CL has a .png file under the screenshots directory for a grd
4695 # file, warn the developer. Actual images should never be checked into the
4696 # Chrome repo.
4697 #
4698 # - If the CL contains modified or new messages in grd files and doesn't
4699 # contain the corresponding .sha1 files, warn the developer to add images
4700 # and upload them via tools/translation/upload_screenshots.py.
4701 #
4702 # - If the CL contains modified or new messages in grd files and the
4703 # corresponding .sha1 files, everything looks good.
4704 #
4705 # - If the CL contains removed messages in grd files but the corresponding
4706 # .sha1 files aren't removed, warn the developer to remove them.
4707 unnecessary_screenshots = []
4708 missing_sha1 = []
4709 unnecessary_sha1_files = []
4710
4711
4712 def _CheckScreenshotAdded(screenshots_dir, message_id):
4713 sha1_path = input_api.os_path.join(
4714 screenshots_dir, message_id + '.png.sha1')
4715 if sha1_path not in new_or_added_paths:
4716 missing_sha1.append(sha1_path)
4717
4718
4719 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4720 sha1_path = input_api.os_path.join(
4721 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034722 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144723 unnecessary_sha1_files.append(sha1_path)
4724
meacer8c0d3832019-12-26 21:46:164725 try:
4726 old_sys_path = sys.path
4727 sys.path = sys.path + [input_api.os_path.join(
4728 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4729 from helper import grd_helper
4730 finally:
4731 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144732
4733 for f in affected_grds:
4734 file_path = f.LocalPath()
4735 old_id_to_msg_map = {}
4736 new_id_to_msg_map = {}
Mustafa Emre Acerd697ac92020-02-06 19:03:384737 # Note that this code doesn't check if the file has been deleted. This is
4738 # OK because it only uses the old and new file contents and doesn't load
4739 # the file via its path.
4740 # It's also possible that a file's content refers to a renamed or deleted
4741 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
4742 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
4743 # .grdp files.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144744 if file_path.endswith('.grdp'):
4745 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584746 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394747 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144748 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584749 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394750 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144751 else:
meacerff8a9b62019-12-10 19:43:584752 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144753 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584754 old_id_to_msg_map = grd_helper.GetGrdMessages(
4755 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144756 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584757 new_id_to_msg_map = grd_helper.GetGrdMessages(
4758 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144759
4760 # Compute added, removed and modified message IDs.
4761 old_ids = set(old_id_to_msg_map)
4762 new_ids = set(new_id_to_msg_map)
4763 added_ids = new_ids - old_ids
4764 removed_ids = old_ids - new_ids
4765 modified_ids = set([])
4766 for key in old_ids.intersection(new_ids):
4767 if (old_id_to_msg_map[key].FormatXml()
4768 != new_id_to_msg_map[key].FormatXml()):
4769 modified_ids.add(key)
4770
4771 grd_name, ext = input_api.os_path.splitext(
4772 input_api.os_path.basename(file_path))
4773 screenshots_dir = input_api.os_path.join(
4774 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4775
4776 # Check the screenshot directory for .png files. Warn if there is any.
4777 for png_path in affected_png_paths:
4778 if png_path.startswith(screenshots_dir):
4779 unnecessary_screenshots.append(png_path)
4780
4781 for added_id in added_ids:
4782 _CheckScreenshotAdded(screenshots_dir, added_id)
4783
4784 for modified_id in modified_ids:
4785 _CheckScreenshotAdded(screenshots_dir, modified_id)
4786
4787 for removed_id in removed_ids:
4788 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4789
4790 results = []
4791 if unnecessary_screenshots:
4792 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394793 'Do not include actual screenshots in the changelist. Run '
4794 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144795 sorted(unnecessary_screenshots)))
4796
4797 if missing_sha1:
4798 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394799 'You are adding or modifying UI strings.\n'
4800 'To ensure the best translations, take screenshots of the relevant UI '
4801 '(https://g.co/chrome/translation) and add these files to your '
4802 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144803
4804 if unnecessary_sha1_files:
4805 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394806 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144807 sorted(unnecessary_sha1_files)))
4808
4809 return results
Mustafa Emre Acer51f2f742020-03-09 19:41:124810
4811
4812def _CheckTranslationExpectations(input_api, output_api,
4813 repo_root=None,
4814 translation_expectations_path=None,
4815 grd_files=None):
4816 import sys
4817 affected_grds = [f for f in input_api.AffectedFiles()
4818 if (f.LocalPath().endswith('.grd') or
4819 f.LocalPath().endswith('.grdp'))]
4820 if not affected_grds:
4821 return []
4822
4823 try:
4824 old_sys_path = sys.path
4825 sys.path = sys.path + [
4826 input_api.os_path.join(
4827 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4828 from helper import git_helper
4829 from helper import translation_helper
4830 finally:
4831 sys.path = old_sys_path
4832
4833 # Check that translation expectations can be parsed and we can get a list of
4834 # translatable grd files. |repo_root| and |translation_expectations_path| are
4835 # only passed by tests.
4836 if not repo_root:
4837 repo_root = input_api.PresubmitLocalPath()
4838 if not translation_expectations_path:
4839 translation_expectations_path = input_api.os_path.join(
4840 repo_root, 'tools', 'gritsettings',
4841 'translation_expectations.pyl')
4842 if not grd_files:
4843 grd_files = git_helper.list_grds_in_repository(repo_root)
4844
4845 try:
4846 translation_helper.get_translatable_grds(repo_root, grd_files,
4847 translation_expectations_path)
4848 except Exception as e:
4849 return [output_api.PresubmitNotifyResult(
4850 'Failed to get a list of translatable grd files. This happens when:\n'
4851 ' - One of the modified grd or grdp files cannot be parsed or\n'
4852 ' - %s is not updated.\n'
4853 'Stack:\n%s' % (translation_expectations_path, str(e)))]
4854 return []