blob: 04cc925007e03a19ef4744541ebbfc746af79a45 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0413 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py",
14 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py",
15 r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
16 r"^net[\\/]tools[\\/]spdyshark[\\/].*",
17 r"^skia[\\/].*",
Kent Tamura32dbbcb2018-11-30 12:28:4918 r"^third_party[\\/]blink[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0419 r"^third_party[\\/]breakpad[\\/].*",
Darwin Huangd74a9d32019-07-17 17:58:4620 # sqlite is an imported third party dependency.
21 r"^third_party[\\/]sqlite[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0422 r"^v8[\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5324 r".+_autogen\.h$",
John Budorick1e701d322019-09-11 23:35:1225 r".+_pb2\.py$",
Egor Paskoce145c42018-09-28 19:31:0426 r".+[\\/]pnacl_shim\.c$",
27 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
Egor Paskoce145c42018-09-28 19:31:0428 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1429 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0430 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5431 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0432 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4033)
[email protected]ca8d1982009-02-19 16:33:1234
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Fragment of a regular expression that matches C++ and Objective-C++
37# implementation files.
38_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
39
wnwenbdc444e2016-05-25 13:44:1540
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1941# Fragment of a regular expression that matches C++ and Objective-C++
42# header files.
43_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
44
45
[email protected]06e6d0ff2012-12-11 01:36:4446# Regular expression that matches code only used for test binaries
47# (best effort).
48_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0449 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4450 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4451 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1252 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1853 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4454 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0455 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0556 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0457 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4758 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0459 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0860 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0461 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4162 # EarlGrey app side code for tests.
63 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4464)
[email protected]ca8d1982009-02-19 16:33:1265
Daniel Bratell609102be2019-03-27 20:53:2166_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1567
[email protected]eea609a2011-11-18 13:10:1268_TEST_ONLY_WARNING = (
69 'You might be calling functions intended only for testing from\n'
70 'production code. It is OK to ignore this warning if you know what\n'
71 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0772 'not perfect. The commit queue will not block on this warning,\n'
73 'however the android-binary-size trybot will block if the method\n'
74 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1275
76
[email protected]cf9b78f2012-11-14 11:40:2877_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4078 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2179 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
80 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2881
Michael Thiessen44457642020-02-06 00:24:1582# Format: Sequence of tuples containing:
83# * Full import path.
84# * Sequence of strings to show when the pattern matches.
85# * Sequence of path or filename exceptions to this rule
86_BANNED_JAVA_IMPORTS = (
87 (
88 'java.net.URI',
89 (
90 'Use org.chromium.url.GURL instead of java.net.URI, where possible.',
91 ),
92 (
93 'net/android/javatests/src/org/chromium/net/'
94 'AndroidProxySelectorTest.java',
95 'components/cronet/',
96 ),
97 ),
98)
wnwenbdc444e2016-05-25 13:44:1599
Daniel Bratell609102be2019-03-27 20:53:21100# Format: Sequence of tuples containing:
101# * String pattern or, if starting with a slash, a regular expression.
102# * Sequence of strings to show when the pattern matches.
103# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:41104_BANNED_JAVA_FUNCTIONS = (
105 (
106 'StrictMode.allowThreadDiskReads()',
107 (
108 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
109 'directly.',
110 ),
111 False,
112 ),
113 (
114 'StrictMode.allowThreadDiskWrites()',
115 (
116 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
117 'directly.',
118 ),
119 False,
120 ),
121)
122
Daniel Bratell609102be2019-03-27 20:53:21123# Format: Sequence of tuples containing:
124# * String pattern or, if starting with a slash, a regular expression.
125# * Sequence of strings to show when the pattern matches.
126# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59127_BANNED_OBJC_FUNCTIONS = (
128 (
129 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59132 'prohibited. Please use CrTrackingArea instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 False,
136 ),
137 (
[email protected]eaae1972014-04-16 04:17:26138 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20139 (
140 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59141 'instead.',
142 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
143 ),
144 False,
145 ),
146 (
147 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20148 (
149 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59150 'Please use |convertPoint:(point) fromView:nil| instead.',
151 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
152 ),
153 True,
154 ),
155 (
156 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59159 'Please use |convertPoint:(point) toView:nil| instead.',
160 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
161 ),
162 True,
163 ),
164 (
165 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59168 'Please use |convertRect:(point) fromView:nil| instead.',
169 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
170 ),
171 True,
172 ),
173 (
174 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20175 (
176 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59177 'Please use |convertRect:(point) toView:nil| instead.',
178 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
179 ),
180 True,
181 ),
182 (
183 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20184 (
185 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59186 'Please use |convertSize:(point) fromView:nil| instead.',
187 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
188 ),
189 True,
190 ),
191 (
192 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20193 (
194 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59195 'Please use |convertSize:(point) toView:nil| instead.',
196 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
197 ),
198 True,
199 ),
jif65398702016-10-27 10:19:48200 (
201 r"/\s+UTF8String\s*]",
202 (
203 'The use of -[NSString UTF8String] is dangerous as it can return null',
204 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
205 'Please use |SysNSStringToUTF8| instead.',
206 ),
207 True,
208 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34209 (
210 r'__unsafe_unretained',
211 (
212 'The use of __unsafe_unretained is almost certainly wrong, unless',
213 'when interacting with NSFastEnumeration or NSInvocation.',
214 'Please use __weak in files build with ARC, nothing otherwise.',
215 ),
216 False,
217 ),
Avi Drissman7382afa02019-04-29 23:27:13218 (
219 'freeWhenDone:NO',
220 (
221 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
222 'Foundation types is prohibited.',
223 ),
224 True,
225 ),
[email protected]127f18ec2012-06-16 05:05:59226)
227
Daniel Bratell609102be2019-03-27 20:53:21228# Format: Sequence of tuples containing:
229# * String pattern or, if starting with a slash, a regular expression.
230# * Sequence of strings to show when the pattern matches.
231# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54232_BANNED_IOS_OBJC_FUNCTIONS = (
233 (
234 r'/\bTEST[(]',
235 (
236 'TEST() macro should not be used in Objective-C++ code as it does not ',
237 'drain the autorelease pool at the end of the test. Use TEST_F() ',
238 'macro instead with a fixture inheriting from PlatformTest (or a ',
239 'typedef).'
240 ),
241 True,
242 ),
243 (
244 r'/\btesting::Test\b',
245 (
246 'testing::Test should not be used in Objective-C++ code as it does ',
247 'not drain the autorelease pool at the end of the test. Use ',
248 'PlatformTest instead.'
249 ),
250 True,
251 ),
252)
253
Peter K. Lee6c03ccff2019-07-15 14:40:05254# Format: Sequence of tuples containing:
255# * String pattern or, if starting with a slash, a regular expression.
256# * Sequence of strings to show when the pattern matches.
257# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
258_BANNED_IOS_EGTEST_FUNCTIONS = (
259 (
260 r'/\bEXPECT_OCMOCK_VERIFY\b',
261 (
262 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
263 'it is meant for GTests. Use [mock verify] instead.'
264 ),
265 True,
266 ),
267)
268
danakj7a2b7082019-05-21 21:13:51269# Directories that contain deprecated Bind() or Callback types.
270# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36271# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51272# echo "-- $i"
danakj710b4c02019-11-28 16:08:45273# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51274# done
275#
276# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
277# when they have been converted to modern callback types (OnceCallback,
278# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
279# checks for them and prevent regressions.
280_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
danakj7a2b7082019-05-21 21:13:51281 '^apps/',
danakj7a2b7082019-05-21 21:13:51282 '^base/callback.h', # Intentional.
283 '^chrome/app/',
284 '^chrome/browser/',
285 '^chrome/chrome_elf/',
danakj7a2b7082019-05-21 21:13:51286 '^chrome/common/',
287 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51288 '^chrome/renderer/',
289 '^chrome/services/',
290 '^chrome/test/',
291 '^chrome/tools/',
292 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51293 '^chromecast/media/',
294 '^chromecast/metrics/',
295 '^chromecast/net/',
296 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51297 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51298 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51299 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51300 '^components/arc/',
301 '^components/assist_ranker/',
302 '^components/autofill/',
303 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51304 '^components/browser_watcher/',
danakj7a2b7082019-05-21 21:13:51305 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51306 '^components/chromeos_camera/',
307 '^components/component_updater/',
308 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51309 '^components/cronet/',
310 '^components/data_reduction_proxy/',
danakj7a2b7082019-05-21 21:13:51311 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36312 '^components/dom_distiller/',
danakj7a2b7082019-05-21 21:13:51313 '^components/download/',
314 '^components/drive/',
315 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51316 '^components/feature_engagement/',
317 '^components/feedback/',
318 '^components/flags_ui/',
319 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51320 '^components/guest_view/',
321 '^components/heap_profiling/',
322 '^components/history/',
323 '^components/image_fetcher/',
324 '^components/invalidation/',
325 '^components/keyed_service/',
326 '^components/login/',
327 '^components/metrics/',
328 '^components/metrics_services_manager/',
329 '^components/nacl/',
330 '^components/navigation_interception/',
331 '^components/net_log/',
332 '^components/network_time/',
333 '^components/ntp_snippets/',
334 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51335 '^components/offline_pages/',
336 '^components/omnibox/',
337 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51338 '^components/password_manager/',
339 '^components/payments/',
340 '^components/plugins/',
341 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51342 '^components/proxy_config/',
343 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51344 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51345 '^components/rlz/',
346 '^components/safe_browsing/',
347 '^components/search_engines/',
348 '^components/search_provider_logos/',
349 '^components/security_interstitials/',
350 '^components/security_state/',
351 '^components/services/',
352 '^components/sessions/',
353 '^components/signin/',
354 '^components/ssl_errors/',
355 '^components/storage_monitor/',
356 '^components/subresource_filter/',
357 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51358 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51359 '^components/sync_preferences/',
360 '^components/sync_sessions/',
361 '^components/test/',
362 '^components/tracing/',
363 '^components/translate/',
364 '^components/ukm/',
365 '^components/update_client/',
366 '^components/upload_list/',
367 '^components/variations/',
368 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51369 '^components/webcrypto/',
370 '^components/webdata/',
371 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51372 '^device/bluetooth/',
Alan Cutter04a00642020-03-02 01:45:20373 '^extensions/browser/',
374 '^extensions/renderer/',
375 '^extensions/shell/',
376 '^extensions/test/',
danakj7a2b7082019-05-21 21:13:51377 '^google_apis/dive/',
danakj7a2b7082019-05-21 21:13:51378 '^google_apis/gcm/',
danakj7a2b7082019-05-21 21:13:51379 '^ios/chrome/',
380 '^ios/components/',
381 '^ios/net/',
382 '^ios/web/',
383 '^ios/web_view/',
384 '^ipc/',
385 '^media/audio/',
386 '^media/base/',
danakjc8576092019-11-26 19:01:36387 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51388 '^media/capture/',
389 '^media/cast/',
390 '^media/cdm/',
391 '^media/device_monitors/',
392 '^media/ffmpeg/',
393 '^media/filters/',
394 '^media/formats/',
395 '^media/gpu/',
396 '^media/mojo/',
397 '^media/muxers/',
398 '^media/remoting/',
399 '^media/renderers/',
400 '^media/test/',
danakj7a2b7082019-05-21 21:13:51401 '^net/',
402 '^ppapi/proxy/',
403 '^ppapi/shared_impl/',
404 '^ppapi/tests/',
405 '^ppapi/thunk/',
406 '^remoting/base/',
407 '^remoting/client/',
danakj7a2b7082019-05-21 21:13:51408 '^remoting/host/',
409 '^remoting/internal/',
danakj7a2b7082019-05-21 21:13:51410 '^remoting/protocol/',
danakj7a2b7082019-05-21 21:13:51411 '^services/',
danakj7a2b7082019-05-21 21:13:51412 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51413 '^tools/clang/base_bind_rewriters/', # Intentional.
414 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51415))
[email protected]127f18ec2012-06-16 05:05:59416
Daniel Bratell609102be2019-03-27 20:53:21417# Format: Sequence of tuples containing:
418# * String pattern or, if starting with a slash, a regular expression.
419# * Sequence of strings to show when the pattern matches.
420# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
421# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59422_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20423 (
Dave Tapuska98199b612019-07-10 13:30:44424 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53425 (
426 'New code should not use NULL. Use nullptr instead.',
427 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20428 False,
thomasandersone7caaa9b2017-03-29 19:22:53429 (),
430 ),
Peter Kasting94a56c42019-10-25 21:54:04431 (
432 r'/\busing namespace ',
433 (
434 'Using directives ("using namespace x") are banned by the Google Style',
435 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
436 'Explicitly qualify symbols or use using declarations ("using x::foo").',
437 ),
438 True,
439 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
440 ),
Antonio Gomes07300d02019-03-13 20:59:57441 # Make sure that gtest's FRIEND_TEST() macro is not used; the
442 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
443 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53444 (
[email protected]23e6cbc2012-06-16 18:51:20445 'FRIEND_TEST(',
446 (
[email protected]e3c945502012-06-26 20:01:49447 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20448 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
449 ),
450 False,
[email protected]7345da02012-11-27 14:31:49451 (),
[email protected]23e6cbc2012-06-16 18:51:20452 ),
453 (
Dave Tapuska98199b612019-07-10 13:30:44454 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53455 (
456 'Chrome clients wishing to select events on X windows should use',
457 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
458 'you are selecting events from the GPU process, or if you are using',
459 'an XDisplay other than gfx::GetXDisplay().',
460 ),
461 True,
462 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40463 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04464 r"^ui[\\/]gl[\\/].*\.cc$",
465 r"^media[\\/]gpu[\\/].*\.cc$",
466 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53467 ),
468 ),
469 (
Dave Tapuska98199b612019-07-10 13:30:44470 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20471 (
thomasanderson11aa41d2017-06-08 22:22:38472 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20473 ),
474 True,
475 (
Egor Paskoce145c42018-09-28 19:31:04476 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
477 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
478 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20479 ),
480 ),
481 (
tomhudsone2c14d552016-05-26 17:07:46482 'setMatrixClip',
483 (
484 'Overriding setMatrixClip() is prohibited; ',
485 'the base function is deprecated. ',
486 ),
487 True,
488 (),
489 ),
490 (
[email protected]52657f62013-05-20 05:30:31491 'SkRefPtr',
492 (
493 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22494 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31495 ),
496 True,
497 (),
498 ),
499 (
500 'SkAutoRef',
501 (
502 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22503 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31504 ),
505 True,
506 (),
507 ),
508 (
509 'SkAutoTUnref',
510 (
511 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22512 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31513 ),
514 True,
515 (),
516 ),
517 (
518 'SkAutoUnref',
519 (
520 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
521 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22522 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31523 ),
524 True,
525 (),
526 ),
[email protected]d89eec82013-12-03 14:10:59527 (
528 r'/HANDLE_EINTR\(.*close',
529 (
530 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
531 'descriptor will be closed, and it is incorrect to retry the close.',
532 'Either call close directly and ignore its return value, or wrap close',
533 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
534 ),
535 True,
536 (),
537 ),
538 (
539 r'/IGNORE_EINTR\((?!.*close)',
540 (
541 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
542 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
543 ),
544 True,
545 (
546 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04547 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
548 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59549 ),
550 ),
[email protected]ec5b3f02014-04-04 18:43:43551 (
552 r'/v8::Extension\(',
553 (
554 'Do not introduce new v8::Extensions into the code base, use',
555 'gin::Wrappable instead. See http://crbug.com/334679',
556 ),
557 True,
[email protected]f55c90ee62014-04-12 00:50:03558 (
Egor Paskoce145c42018-09-28 19:31:04559 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03560 ),
[email protected]ec5b3f02014-04-04 18:43:43561 ),
skyostilf9469f72015-04-20 10:38:52562 (
jame2d1a952016-04-02 00:27:10563 '#pragma comment(lib,',
564 (
565 'Specify libraries to link with in build files and not in the source.',
566 ),
567 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41568 (
tzik3f295992018-12-04 20:32:23569 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04570 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41571 ),
jame2d1a952016-04-02 00:27:10572 ),
fdorayc4ac18d2017-05-01 21:39:59573 (
Gabriel Charette7cc6c432018-04-25 20:52:02574 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59575 (
576 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
577 ),
578 False,
579 (),
580 ),
581 (
Gabriel Charette7cc6c432018-04-25 20:52:02582 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59583 (
584 'Consider using THREAD_CHECKER macros instead of the class directly.',
585 ),
586 False,
587 (),
588 ),
dbeamb6f4fde2017-06-15 04:03:06589 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06590 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
591 (
592 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
593 'deprecated (http://crbug.com/634507). Please avoid converting away',
594 'from the Time types in Chromium code, especially if any math is',
595 'being done on time values. For interfacing with platform/library',
596 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
597 'type converter methods instead. For faking TimeXXX values (for unit',
598 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
599 'other use cases, please contact base/time/OWNERS.',
600 ),
601 False,
602 (),
603 ),
604 (
dbeamb6f4fde2017-06-15 04:03:06605 'CallJavascriptFunctionUnsafe',
606 (
607 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
608 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
609 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
610 ),
611 False,
612 (
Egor Paskoce145c42018-09-28 19:31:04613 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
614 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
615 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06616 ),
617 ),
dskiba1474c2bfd62017-07-20 02:19:24618 (
619 'leveldb::DB::Open',
620 (
621 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
622 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
623 "Chrome's tracing, making their memory usage visible.",
624 ),
625 True,
626 (
627 r'^third_party/leveldatabase/.*\.(cc|h)$',
628 ),
Gabriel Charette0592c3a2017-07-26 12:02:04629 ),
630 (
Chris Mumfordc38afb62017-10-09 17:55:08631 'leveldb::NewMemEnv',
632 (
633 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58634 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
635 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08636 ),
637 True,
638 (
639 r'^third_party/leveldatabase/.*\.(cc|h)$',
640 ),
641 ),
642 (
Gabriel Charetted9839bc2017-07-29 14:17:47643 'RunLoop::QuitCurrent',
644 (
Robert Liao64b7ab22017-08-04 23:03:43645 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
646 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47647 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41648 False,
Gabriel Charetted9839bc2017-07-29 14:17:47649 (),
Gabriel Charettea44975052017-08-21 23:14:04650 ),
651 (
652 'base::ScopedMockTimeMessageLoopTaskRunner',
653 (
Gabriel Charette87cc1af2018-04-25 20:52:51654 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11655 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51656 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
657 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
658 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04659 ),
Gabriel Charette87cc1af2018-04-25 20:52:51660 False,
Gabriel Charettea44975052017-08-21 23:14:04661 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57662 ),
663 (
Dave Tapuska98199b612019-07-10 13:30:44664 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57665 (
666 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02667 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57668 ),
669 True,
670 (),
Francois Doray43670e32017-09-27 12:40:38671 ),
672 (
Peter Kasting991618a62019-06-17 22:00:09673 r'/\bstd::stoi\b',
674 (
675 'std::stoi uses exceptions to communicate results. ',
676 'Use base::StringToInt() instead.',
677 ),
678 True,
679 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
680 ),
681 (
682 r'/\bstd::stol\b',
683 (
684 'std::stol uses exceptions to communicate results. ',
685 'Use base::StringToInt() instead.',
686 ),
687 True,
688 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
689 ),
690 (
691 r'/\bstd::stoul\b',
692 (
693 'std::stoul uses exceptions to communicate results. ',
694 'Use base::StringToUint() instead.',
695 ),
696 True,
697 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
698 ),
699 (
700 r'/\bstd::stoll\b',
701 (
702 'std::stoll uses exceptions to communicate results. ',
703 'Use base::StringToInt64() instead.',
704 ),
705 True,
706 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
707 ),
708 (
709 r'/\bstd::stoull\b',
710 (
711 'std::stoull uses exceptions to communicate results. ',
712 'Use base::StringToUint64() instead.',
713 ),
714 True,
715 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
716 ),
717 (
718 r'/\bstd::stof\b',
719 (
720 'std::stof uses exceptions to communicate results. ',
721 'For locale-independent values, e.g. reading numbers from disk',
722 'profiles, use base::StringToDouble().',
723 'For user-visible values, parse using ICU.',
724 ),
725 True,
726 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
727 ),
728 (
729 r'/\bstd::stod\b',
730 (
731 'std::stod uses exceptions to communicate results. ',
732 'For locale-independent values, e.g. reading numbers from disk',
733 'profiles, use base::StringToDouble().',
734 'For user-visible values, parse using ICU.',
735 ),
736 True,
737 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
738 ),
739 (
740 r'/\bstd::stold\b',
741 (
742 'std::stold uses exceptions to communicate results. ',
743 'For locale-independent values, e.g. reading numbers from disk',
744 'profiles, use base::StringToDouble().',
745 'For user-visible values, parse using ICU.',
746 ),
747 True,
748 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
749 ),
750 (
Daniel Bratell69334cc2019-03-26 11:07:45751 r'/\bstd::to_string\b',
752 (
753 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09754 'For locale-independent strings, e.g. writing numbers to disk',
755 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45756 'For user-visible strings, use base::FormatNumber() and',
757 'the related functions in base/i18n/number_formatting.h.',
758 ),
Peter Kasting991618a62019-06-17 22:00:09759 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21760 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45761 ),
762 (
763 r'/\bstd::shared_ptr\b',
764 (
765 'std::shared_ptr should not be used. Use scoped_refptr instead.',
766 ),
767 True,
Andreas Haas63f58792019-11-07 10:56:44768 [_THIRD_PARTY_EXCEPT_BLINK,
769 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
770 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21771 ),
772 (
Peter Kasting991618a62019-06-17 22:00:09773 r'/\bstd::weak_ptr\b',
774 (
775 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
776 ),
777 True,
778 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
779 ),
780 (
Daniel Bratell609102be2019-03-27 20:53:21781 r'/\blong long\b',
782 (
783 'long long is banned. Use stdint.h if you need a 64 bit number.',
784 ),
785 False, # Only a warning since it is already used.
786 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
787 ),
788 (
789 r'/\bstd::bind\b',
790 (
791 'std::bind is banned because of lifetime risks.',
792 'Use base::BindOnce or base::BindRepeating instead.',
793 ),
794 True,
795 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
796 ),
797 (
798 r'/\b#include <chrono>\b',
799 (
800 '<chrono> overlaps with Time APIs in base. Keep using',
801 'base classes.',
802 ),
803 True,
804 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
805 ),
806 (
807 r'/\b#include <exception>\b',
808 (
809 'Exceptions are banned and disabled in Chromium.',
810 ),
811 True,
812 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
813 ),
814 (
815 r'/\bstd::function\b',
816 (
817 'std::function is banned. Instead use base::Callback which directly',
818 'supports Chromium\'s weak pointers, ref counting and more.',
819 ),
Peter Kasting991618a62019-06-17 22:00:09820 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21821 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
822 ),
823 (
824 r'/\b#include <random>\b',
825 (
826 'Do not use any random number engines from <random>. Instead',
827 'use base::RandomBitGenerator.',
828 ),
829 True,
830 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
831 ),
832 (
833 r'/\bstd::ratio\b',
834 (
835 'std::ratio is banned by the Google Style Guide.',
836 ),
837 True,
838 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45839 ),
840 (
Francois Doray43670e32017-09-27 12:40:38841 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
842 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
843 (
844 'Use the new API in base/threading/thread_restrictions.h.',
845 ),
Gabriel Charette04b138f2018-08-06 00:03:22846 False,
Francois Doray43670e32017-09-27 12:40:38847 (),
848 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38849 (
danakj7a2b7082019-05-21 21:13:51850 r'/\bbase::Bind\(',
851 (
852 'Please use base::Bind{Once,Repeating} instead',
853 'of base::Bind. (crbug.com/714018)',
854 ),
855 False,
Erik Staaba737d7602019-11-25 18:41:07856 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51857 ),
858 (
859 r'/\bbase::Callback[<:]',
860 (
861 'Please use base::{Once,Repeating}Callback instead',
862 'of base::Callback. (crbug.com/714018)',
863 ),
864 False,
Erik Staaba737d7602019-11-25 18:41:07865 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51866 ),
867 (
868 r'/\bbase::Closure\b',
869 (
870 'Please use base::{Once,Repeating}Closure instead',
871 'of base::Closure. (crbug.com/714018)',
872 ),
873 False,
Erik Staaba737d7602019-11-25 18:41:07874 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51875 ),
876 (
Michael Giuffrida7f93d6922019-04-19 14:39:58877 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19878 (
879 'RunMessageLoop is deprecated, use RunLoop instead.',
880 ),
881 False,
882 (),
883 ),
884 (
Dave Tapuska98199b612019-07-10 13:30:44885 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19886 (
887 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
888 ),
889 False,
890 (),
891 ),
892 (
Dave Tapuska98199b612019-07-10 13:30:44893 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19894 (
895 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
896 "if you're convinced you need this.",
897 ),
898 False,
899 (),
900 ),
901 (
Dave Tapuska98199b612019-07-10 13:30:44902 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19903 (
904 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04905 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19906 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
907 'async events instead of flushing threads.',
908 ),
909 False,
910 (),
911 ),
912 (
913 r'MessageLoopRunner',
914 (
915 'MessageLoopRunner is deprecated, use RunLoop instead.',
916 ),
917 False,
918 (),
919 ),
920 (
Dave Tapuska98199b612019-07-10 13:30:44921 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19922 (
923 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
924 "gab@ if you found a use case where this is the only solution.",
925 ),
926 False,
927 (),
928 ),
929 (
Victor Costane48a2e82019-03-15 22:02:34930 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16931 (
Victor Costane48a2e82019-03-15 22:02:34932 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16933 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
934 ),
935 True,
936 (
937 r'^sql/initialization\.(cc|h)$',
938 r'^third_party/sqlite/.*\.(c|cc|h)$',
939 ),
940 ),
Matt Menke7f520a82018-03-28 21:38:37941 (
942 'net::URLFetcher',
943 (
944 'net::URLFetcher should no longer be used in content embedders. ',
945 'Instead, use network::SimpleURLLoader instead, which supports ',
946 'an out-of-process network stack. ',
947 'net::URLFetcher may still be used in binaries that do not embed',
948 'content.',
949 ),
Matt Menke59716d02018-04-05 12:45:53950 False,
Matt Menke7f520a82018-03-28 21:38:37951 (
Egor Paskoce145c42018-09-28 19:31:04952 r'^ios[\\/].*\.(cc|h)$',
953 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37954 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04955 r'^net[\\/].*\.(cc|h)$',
956 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43957 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37958 ),
959 ),
jdoerried7d10ab2018-04-27 10:46:13960 (
Dave Tapuska98199b612019-07-10 13:30:44961 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47962 (
963 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
964 'base::RandomShuffle instead.'
965 ),
966 True,
967 (),
968 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24969 (
970 'ios/web/public/test/http_server',
971 (
972 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
973 ),
974 False,
975 (),
976 ),
Robert Liao764c9492019-01-24 18:46:28977 (
978 'GetAddressOf',
979 (
980 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46981 'implicated in a few leaks. Use operator& instead. See ',
982 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28983 ),
984 True,
985 (),
986 ),
Antonio Gomes07300d02019-03-13 20:59:57987 (
988 'DEFINE_TYPE_CASTS',
989 (
990 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
991 '//third_party/blink/renderer/platform/casting.h.'
992 ),
993 True,
994 (
995 r'^third_party/blink/renderer/.*\.(cc|h)$',
996 ),
997 ),
Carlos Knippschildab192b8c2019-04-08 20:02:38998 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:45999 r'/\bIsHTML.+Element\(\b',
1000 (
1001 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1002 ' helpers IsA<HTMLXXXXElement> from ',
1003 '//third_party/blink/renderer/platform/casting.h.'
1004 ),
1005 False,
1006 (
1007 r'^third_party/blink/renderer/.*\.(cc|h)$',
1008 ),
1009 ),
1010 (
1011 r'/\bToHTML.+Element(|OrNull)\(\b',
1012 (
1013 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1014 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1015 'and DynamicTo<HTMLXXXXElement> from ',
1016 '//third_party/blink/renderer/platform/casting.h.'
1017 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1018 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1019 ),
1020 False,
1021 (
1022 r'^third_party/blink/renderer/.*\.(cc|h)$',
1023 ),
1024 ),
1025 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371026 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381027 (
1028 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1029 ),
1030 True,
1031 (),
1032 ),
Ben Lewisa9514602019-04-29 17:53:051033 (
1034 'SHFileOperation',
1035 (
1036 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1037 'complex functions to achieve the same goals. Use IFileOperation for ',
1038 'any esoteric actions instead.'
1039 ),
1040 True,
1041 (),
1042 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181043 (
Cliff Smolinsky81951642019-04-30 21:39:511044 'StringFromGUID2',
1045 (
1046 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1047 'Use base::win::String16FromGUID instead.'
1048 ),
1049 True,
1050 (
1051 r'/base/win/win_util_unittest.cc'
1052 ),
1053 ),
1054 (
1055 'StringFromCLSID',
1056 (
1057 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1058 'Use base::win::String16FromGUID instead.'
1059 ),
1060 True,
1061 (
1062 r'/base/win/win_util_unittest.cc'
1063 ),
1064 ),
1065 (
Avi Drissman7382afa02019-04-29 23:27:131066 'kCFAllocatorNull',
1067 (
1068 'The use of kCFAllocatorNull with the NoCopy creation of ',
1069 'CoreFoundation types is prohibited.',
1070 ),
1071 True,
1072 (),
1073 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291074 (
1075 'mojo::ConvertTo',
1076 (
1077 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1078 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1079 'StringTraits if you would like to convert between custom types and',
1080 'the wire format of mojom types.'
1081 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221082 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291083 (
Wezf89dec092019-09-11 19:38:331084 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1085 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291086 r'^third_party/blink/.*\.(cc|h)$',
1087 r'^content/renderer/.*\.(cc|h)$',
1088 ),
1089 ),
Robert Liao1d78df52019-11-11 20:02:011090 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161091 'GetInterfaceProvider',
1092 (
1093 'InterfaceProvider is deprecated.',
1094 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1095 'or Platform::GetBrowserInterfaceBroker.'
1096 ),
1097 False,
1098 (),
1099 ),
1100 (
Robert Liao1d78df52019-11-11 20:02:011101 'CComPtr',
1102 (
1103 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1104 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1105 'details.'
1106 ),
1107 False,
1108 (),
1109 ),
Xiaohan Wang72bd2ba2020-02-18 21:38:201110 (
1111 r'/\b(IFACE|STD)METHOD_?\(',
1112 (
1113 'IFACEMETHOD() and STDMETHOD() make code harder to format and read.',
1114 'Instead, always use IFACEMETHODIMP in the declaration.'
1115 ),
1116 False,
1117 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
1118 ),
[email protected]127f18ec2012-06-16 05:05:591119)
1120
Mario Sanchez Prada2472cab2019-09-18 10:58:311121# Format: Sequence of tuples containing:
1122# * String pattern or, if starting with a slash, a regular expression.
1123# * Sequence of strings to show when the pattern matches.
1124_DEPRECATED_MOJO_TYPES = (
1125 (
1126 r'/\bmojo::AssociatedBinding\b',
1127 (
1128 'mojo::AssociatedBinding<Interface> is deprecated.',
1129 'Use mojo::AssociatedReceiver<Interface> instead.',
1130 ),
1131 ),
1132 (
1133 r'/\bmojo::AssociatedBindingSet\b',
1134 (
1135 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1136 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1137 ),
1138 ),
1139 (
1140 r'/\bmojo::AssociatedInterfacePtr\b',
1141 (
1142 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1143 'Use mojo::AssociatedRemote<Interface> instead.',
1144 ),
1145 ),
1146 (
1147 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1148 (
1149 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1150 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1151 ),
1152 ),
1153 (
1154 r'/\bmojo::AssociatedInterfaceRequest\b',
1155 (
1156 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1157 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1158 ),
1159 ),
1160 (
1161 r'/\bmojo::Binding\b',
1162 (
1163 'mojo::Binding<Interface> is deprecated.',
1164 'Use mojo::Receiver<Interface> instead.',
1165 ),
1166 ),
1167 (
1168 r'/\bmojo::BindingSet\b',
1169 (
1170 'mojo::BindingSet<Interface> is deprecated.',
1171 'Use mojo::ReceiverSet<Interface> instead.',
1172 ),
1173 ),
1174 (
1175 r'/\bmojo::InterfacePtr\b',
1176 (
1177 'mojo::InterfacePtr<Interface> is deprecated.',
1178 'Use mojo::Remote<Interface> instead.',
1179 ),
1180 ),
1181 (
1182 r'/\bmojo::InterfacePtrInfo\b',
1183 (
1184 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1185 'Use mojo::PendingRemote<Interface> instead.',
1186 ),
1187 ),
1188 (
1189 r'/\bmojo::InterfaceRequest\b',
1190 (
1191 'mojo::InterfaceRequest<Interface> is deprecated.',
1192 'Use mojo::PendingReceiver<Interface> instead.',
1193 ),
1194 ),
1195 (
1196 r'/\bmojo::MakeRequest\b',
1197 (
1198 'mojo::MakeRequest is deprecated.',
1199 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1200 ),
1201 ),
1202 (
1203 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1204 (
1205 'mojo::MakeRequest is deprecated.',
1206 'Use mojo::AssociatedRemote::'
1207 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1208 ),
1209 ),
1210 (
1211 r'/\bmojo::MakeStrongBinding\b',
1212 (
1213 'mojo::MakeStrongBinding is deprecated.',
1214 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1215 'mojo::MakeSelfOwnedReceiver() instead.',
1216 ),
1217 ),
1218 (
1219 r'/\bmojo::MakeStrongAssociatedBinding\b',
1220 (
1221 'mojo::MakeStrongAssociatedBinding is deprecated.',
1222 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1223 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1224 ),
1225 ),
1226 (
1227 r'/\bmojo::StrongAssociatedBindingSet\b',
1228 (
1229 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1230 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1231 ),
1232 ),
1233 (
1234 r'/\bmojo::StrongBindingSet\b',
1235 (
1236 'mojo::StrongBindingSet<Interface> is deprecated.',
1237 'Use mojo::UniqueReceiverSet<Interface> instead.',
1238 ),
1239 ),
1240)
wnwenbdc444e2016-05-25 13:44:151241
mlamouria82272622014-09-16 18:45:041242_IPC_ENUM_TRAITS_DEPRECATED = (
1243 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501244 'See http://www.chromium.org/Home/chromium-security/education/'
1245 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041246
Stephen Martinis97a394142018-06-07 23:06:051247_LONG_PATH_ERROR = (
1248 'Some files included in this CL have file names that are too long (> 200'
1249 ' characters). If committed, these files will cause issues on Windows. See'
1250 ' https://crbug.com/612667 for more details.'
1251)
1252
Shenghua Zhangbfaa38b82017-11-16 21:58:021253_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041254 r".*[\\/]BuildHooksAndroidImpl\.java",
1255 r".*[\\/]LicenseContentProvider\.java",
1256 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281257 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021258]
[email protected]127f18ec2012-06-16 05:05:591259
Mohamed Heikald048240a2019-11-12 16:57:371260# List of image extensions that are used as resources in chromium.
1261_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1262
Sean Kau46e29bc2017-08-28 16:31:161263# These paths contain test data and other known invalid JSON files.
1264_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041265 r'test[\\/]data[\\/]',
1266 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1267 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041268 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431269 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161270]
1271
1272
[email protected]b00342e7f2013-03-26 16:21:541273_VALID_OS_MACROS = (
1274 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081275 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541276 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121277 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541278 'OS_BSD',
1279 'OS_CAT', # For testing.
1280 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041281 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541282 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371283 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541284 'OS_IOS',
1285 'OS_LINUX',
1286 'OS_MACOSX',
1287 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211288 'OS_NACL_NONSFI',
1289 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121290 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541291 'OS_OPENBSD',
1292 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371293 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541294 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541295 'OS_WIN',
1296)
1297
1298
agrievef32bcc72016-04-04 14:57:401299_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391300 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361301 'base/android/jni_generator/jni_generator.pydeps',
1302 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221303 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'build/android/gyp/aar.pydeps',
1305 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271306 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361307 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381308 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361309 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111310 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361311 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361312 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361313 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111314 'build/android/gyp/create_app_bundle_apks.pydeps',
1315 'build/android/gyp/create_app_bundle.pydeps',
1316 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361317 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221318 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361319 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591320 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361321 'build/android/gyp/dex.pydeps',
1322 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361323 'build/android/gyp/filter_zip.pydeps',
1324 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361325 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361326 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581327 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361328 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261329 'build/android/gyp/java_cpp_strings.pydeps',
Andrew Grieve5853fbd2020-02-20 17:26:011330 'build/android/gyp/jetify_jar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361331 'build/android/gyp/jinja_template.pydeps',
1332 'build/android/gyp/lint.pydeps',
1333 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361334 'build/android/gyp/merge_manifest.pydeps',
1335 'build/android/gyp/prepare_resources.pydeps',
1336 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241337 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361338 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461339 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561340 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361341 'build/android/incremental_install/generate_android_manifest.pydeps',
1342 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221343 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401344 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041345 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361346 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411347 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051348 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191349 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431350 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021351 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401352]
1353
wnwenbdc444e2016-05-25 13:44:151354
agrievef32bcc72016-04-04 14:57:401355_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421356 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131357 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421358 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1359 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131360 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191361 ('third_party/blink/renderer/bindings/scripts/'
1362 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061363 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221364 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401365]
1366
wnwenbdc444e2016-05-25 13:44:151367
agrievef32bcc72016-04-04 14:57:401368_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1369
1370
Eric Boren6fd2b932018-01-25 15:05:081371# Bypass the AUTHORS check for these accounts.
1372_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591373 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451374 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591375 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521376 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1377 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041378 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271379 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041380 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301381 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081382
1383
Daniel Bratell65b033262019-04-23 08:17:061384def _IsCPlusPlusFile(input_api, file_path):
1385 """Returns True if this file contains C++-like code (and not Python,
1386 Go, Java, MarkDown, ...)"""
1387
1388 ext = input_api.os_path.splitext(file_path)[1]
1389 # This list is compatible with CppChecker.IsCppFile but we should
1390 # consider adding ".c" to it. If we do that we can use this function
1391 # at more places in the code.
1392 return ext in (
1393 '.h',
1394 '.cc',
1395 '.cpp',
1396 '.m',
1397 '.mm',
1398 )
1399
1400def _IsCPlusPlusHeaderFile(input_api, file_path):
1401 return input_api.os_path.splitext(file_path)[1] == ".h"
1402
1403
1404def _IsJavaFile(input_api, file_path):
1405 return input_api.os_path.splitext(file_path)[1] == ".java"
1406
1407
1408def _IsProtoFile(input_api, file_path):
1409 return input_api.os_path.splitext(file_path)[1] == ".proto"
1410
[email protected]55459852011-08-10 15:17:191411def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1412 """Attempts to prevent use of functions intended only for testing in
1413 non-testing code. For now this is just a best-effort implementation
1414 that ignores header files and may have some false positives. A
1415 better implementation would probably need a proper C++ parser.
1416 """
1417 # We only scan .cc files and the like, as the declaration of
1418 # for-testing functions in header files are hard to distinguish from
1419 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491420 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191421
jochenc0d4808c2015-07-27 09:25:421422 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191423 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091424 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191425 exclusion_pattern = input_api.re.compile(
1426 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1427 base_function_pattern, base_function_pattern))
1428
1429 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441430 black_list = (_EXCLUDED_PATHS +
1431 _TEST_CODE_EXCLUDED_PATHS +
1432 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191433 return input_api.FilterSourceFile(
1434 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491435 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191436 black_list=black_list)
1437
1438 problems = []
1439 for f in input_api.AffectedSourceFiles(FilterFile):
1440 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241441 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031442 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461443 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031444 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191445 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031446 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191447
1448 if problems:
[email protected]f7051d52013-04-02 18:31:421449 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031450 else:
1451 return []
[email protected]55459852011-08-10 15:17:191452
1453
Vaclav Brozek7dbc28c2018-03-27 08:35:231454def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1455 """This is a simplified version of
1456 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1457 """
1458 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1459 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1460 name_pattern = r'ForTest(s|ing)?'
1461 # Describes an occurrence of "ForTest*" inside a // comment.
1462 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1463 # Catch calls.
1464 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1465 # Ignore definitions. (Comments are ignored separately.)
1466 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1467
1468 problems = []
1469 sources = lambda x: input_api.FilterSourceFile(
1470 x,
1471 black_list=(('(?i).*test', r'.*\/junit\/')
1472 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491473 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231474 )
1475 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1476 local_path = f.LocalPath()
1477 is_inside_javadoc = False
1478 for line_number, line in f.ChangedContents():
1479 if is_inside_javadoc and javadoc_end_re.search(line):
1480 is_inside_javadoc = False
1481 if not is_inside_javadoc and javadoc_start_re.search(line):
1482 is_inside_javadoc = True
1483 if is_inside_javadoc:
1484 continue
1485 if (inclusion_re.search(line) and
1486 not comment_re.search(line) and
1487 not exclusion_re.search(line)):
1488 problems.append(
1489 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1490
1491 if problems:
1492 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1493 else:
1494 return []
1495
1496
[email protected]10689ca2011-09-02 02:31:541497def _CheckNoIOStreamInHeaders(input_api, output_api):
1498 """Checks to make sure no .h files include <iostream>."""
1499 files = []
1500 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1501 input_api.re.MULTILINE)
1502 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1503 if not f.LocalPath().endswith('.h'):
1504 continue
1505 contents = input_api.ReadFile(f)
1506 if pattern.search(contents):
1507 files.append(f)
1508
1509 if len(files):
yolandyandaabc6d2016-04-18 18:29:391510 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061511 'Do not #include <iostream> in header files, since it inserts static '
1512 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541513 '#include <ostream>. See http://crbug.com/94794',
1514 files) ]
1515 return []
1516
Danil Chapovalov3518f362018-08-11 16:13:431517def _CheckNoStrCatRedefines(input_api, output_api):
1518 """Checks no windows headers with StrCat redefined are included directly."""
1519 files = []
1520 pattern_deny = input_api.re.compile(
1521 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1522 input_api.re.MULTILINE)
1523 pattern_allow = input_api.re.compile(
1524 r'^#include\s"base/win/windows_defines.inc"',
1525 input_api.re.MULTILINE)
1526 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1527 contents = input_api.ReadFile(f)
1528 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1529 files.append(f.LocalPath())
1530
1531 if len(files):
1532 return [output_api.PresubmitError(
1533 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1534 'directly since they pollute code with StrCat macro. Instead, '
1535 'include matching header from base/win. See http://crbug.com/856536',
1536 files) ]
1537 return []
1538
[email protected]10689ca2011-09-02 02:31:541539
[email protected]72df4e782012-06-21 16:28:181540def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521541 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181542 problems = []
1543 for f in input_api.AffectedFiles():
1544 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1545 continue
1546
1547 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041548 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181549 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1550
1551 if not problems:
1552 return []
1553 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1554 '\n'.join(problems))]
1555
Dominic Battre033531052018-09-24 15:45:341556def _CheckNoDISABLETypoInTests(input_api, output_api):
1557 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1558
1559 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1560 instead of DISABLED_. To filter false positives, reports are only generated
1561 if a corresponding MAYBE_ line exists.
1562 """
1563 problems = []
1564
1565 # The following two patterns are looked for in tandem - is a test labeled
1566 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1567 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1568 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1569
1570 # This is for the case that a test is disabled on all platforms.
1571 full_disable_pattern = input_api.re.compile(
1572 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1573 input_api.re.MULTILINE)
1574
Katie Df13948e2018-09-25 07:33:441575 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341576 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1577 continue
1578
1579 # Search for MABYE_, DISABLE_ pairs.
1580 disable_lines = {} # Maps of test name to line number.
1581 maybe_lines = {}
1582 for line_num, line in f.ChangedContents():
1583 disable_match = disable_pattern.search(line)
1584 if disable_match:
1585 disable_lines[disable_match.group(1)] = line_num
1586 maybe_match = maybe_pattern.search(line)
1587 if maybe_match:
1588 maybe_lines[maybe_match.group(1)] = line_num
1589
1590 # Search for DISABLE_ occurrences within a TEST() macro.
1591 disable_tests = set(disable_lines.keys())
1592 maybe_tests = set(maybe_lines.keys())
1593 for test in disable_tests.intersection(maybe_tests):
1594 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1595
1596 contents = input_api.ReadFile(f)
1597 full_disable_match = full_disable_pattern.search(contents)
1598 if full_disable_match:
1599 problems.append(' %s' % f.LocalPath())
1600
1601 if not problems:
1602 return []
1603 return [
1604 output_api.PresubmitPromptWarning(
1605 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1606 '\n'.join(problems))
1607 ]
1608
[email protected]72df4e782012-06-21 16:28:181609
danakj61c1aa22015-10-26 19:55:521610def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571611 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521612 errors = []
1613 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1614 input_api.re.MULTILINE)
1615 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1616 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1617 continue
1618 for lnum, line in f.ChangedContents():
1619 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171620 errors.append(output_api.PresubmitError(
1621 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571622 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171623 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521624 return errors
1625
1626
Makoto Shimazu3ad422cd2019-05-08 02:35:141627def _FindHistogramNameInChunk(histogram_name, chunk):
1628 """Tries to find a histogram name or prefix in a line.
1629
1630 Returns the existence of the histogram name, or None if it needs more chunk
1631 to determine."""
mcasasb7440c282015-02-04 14:52:191632 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1633 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141634 if '<affected-histogram' in chunk:
1635 # If the tag is not completed, needs more chunk to get the name.
1636 if not '>' in chunk:
1637 return None
1638 if not 'name="' in chunk:
1639 return False
1640 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1641 # expect the only attribute is the name.
1642 histogram_prefix = chunk.split('"')[1]
1643 return histogram_prefix in histogram_name
1644 # Typically the whole histogram name should in the line.
1645 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191646
1647
1648def _CheckUmaHistogramChanges(input_api, output_api):
1649 """Check that UMA histogram names in touched lines can still be found in other
1650 lines of the patch or in histograms.xml. Note that this check would not catch
1651 the reverse: changes in histograms.xml not matched in the code itself."""
1652 touched_histograms = []
1653 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471654 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1655 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1656 name_pattern = r'"(.*?)"'
1657 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1658 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1659 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1660 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1661 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171662 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191663 for f in input_api.AffectedFiles():
1664 # If histograms.xml itself is modified, keep the modified lines for later.
1665 if f.LocalPath().endswith(('histograms.xml')):
1666 histograms_xml_modifications = f.ChangedContents()
1667 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471668 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1669 single_line_re = single_line_c_re
1670 split_line_prefix_re = split_line_c_prefix_re
1671 elif f.LocalPath().endswith(('java')):
1672 single_line_re = single_line_java_re
1673 split_line_prefix_re = split_line_java_prefix_re
1674 else:
mcasasb7440c282015-02-04 14:52:191675 continue
1676 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171677 if last_line_matched_prefix:
1678 suffix_found = split_line_suffix_re.search(line)
1679 if suffix_found :
1680 touched_histograms.append([suffix_found.group(1), f, line_num])
1681 last_line_matched_prefix = False
1682 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061683 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191684 if found:
1685 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171686 continue
1687 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191688
1689 # Search for the touched histogram names in the local modifications to
1690 # histograms.xml, and, if not found, on the base histograms.xml file.
1691 unmatched_histograms = []
1692 for histogram_info in touched_histograms:
1693 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141694 chunk = ''
mcasasb7440c282015-02-04 14:52:191695 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141696 chunk += line
1697 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1698 if histogram_name_found is None:
1699 continue
1700 chunk = ''
mcasasb7440c282015-02-04 14:52:191701 if histogram_name_found:
1702 break
1703 if not histogram_name_found:
1704 unmatched_histograms.append(histogram_info)
1705
eromanb90c82e7e32015-04-01 15:13:491706 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191707 problems = []
1708 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491709 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191710 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451711 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191712 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141713 chunk = ''
mcasasb7440c282015-02-04 14:52:191714 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141715 chunk += line
1716 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1717 chunk)
1718 if histogram_name_found is None:
1719 continue
1720 chunk = ''
mcasasb7440c282015-02-04 14:52:191721 if histogram_name_found:
1722 break
1723 if not histogram_name_found:
1724 problems.append(' [%s:%d] %s' %
1725 (f.LocalPath(), line_num, histogram_name))
1726
1727 if not problems:
1728 return []
1729 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1730 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491731 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191732
wnwenbdc444e2016-05-25 13:44:151733
yolandyandaabc6d2016-04-18 18:29:391734def _CheckFlakyTestUsage(input_api, output_api):
1735 """Check that FlakyTest annotation is our own instead of the android one"""
1736 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1737 files = []
1738 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1739 if f.LocalPath().endswith('Test.java'):
1740 if pattern.search(input_api.ReadFile(f)):
1741 files.append(f)
1742 if len(files):
1743 return [output_api.PresubmitError(
1744 'Use org.chromium.base.test.util.FlakyTest instead of '
1745 'android.test.FlakyTest',
1746 files)]
1747 return []
mcasasb7440c282015-02-04 14:52:191748
wnwenbdc444e2016-05-25 13:44:151749
[email protected]8ea5d4b2011-09-13 21:49:221750def _CheckNoNewWStrings(input_api, output_api):
1751 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271752 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221753 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201754 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571755 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341756 '/win/' in f.LocalPath() or
1757 'chrome_elf' in f.LocalPath() or
1758 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201759 continue
[email protected]8ea5d4b2011-09-13 21:49:221760
[email protected]a11dbe9b2012-08-07 01:32:581761 allowWString = False
[email protected]b5c24292011-11-28 14:38:201762 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581763 if 'presubmit: allow wstring' in line:
1764 allowWString = True
1765 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271766 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581767 allowWString = False
1768 else:
1769 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221770
[email protected]55463aa62011-10-12 00:48:271771 if not problems:
1772 return []
1773 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581774 ' If you are calling a cross-platform API that accepts a wstring, '
1775 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271776 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221777
1778
[email protected]2a8ac9c2011-10-19 17:20:441779def _CheckNoDEPSGIT(input_api, output_api):
1780 """Make sure .DEPS.git is never modified manually."""
1781 if any(f.LocalPath().endswith('.DEPS.git') for f in
1782 input_api.AffectedFiles()):
1783 return [output_api.PresubmitError(
1784 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1785 'automated system based on what\'s in DEPS and your changes will be\n'
1786 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501787 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1788 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441789 'for more information')]
1790 return []
1791
1792
tandriief664692014-09-23 14:51:471793def _CheckValidHostsInDEPS(input_api, output_api):
1794 """Checks that DEPS file deps are from allowed_hosts."""
1795 # Run only if DEPS file has been modified to annoy fewer bystanders.
1796 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1797 return []
1798 # Outsource work to gclient verify
1799 try:
John Budorickf20c0042019-04-25 23:23:401800 gclient_path = input_api.os_path.join(
1801 input_api.PresubmitLocalPath(),
1802 'third_party', 'depot_tools', 'gclient.py')
1803 input_api.subprocess.check_output(
1804 [input_api.python_executable, gclient_path, 'verify'],
1805 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471806 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201807 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471808 return [output_api.PresubmitError(
1809 'DEPS file must have only git dependencies.',
1810 long_text=error.output)]
1811
1812
Mario Sanchez Prada2472cab2019-09-18 10:58:311813def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1814 type_name, message):
1815 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1816
1817 Returns an string composed of the name of the file, the line number where the
1818 match has been found and the additional text passed as |message| in case the
1819 target type name matches the text inside the line passed as parameter.
1820 """
1821 matched = False
1822 if type_name[0:1] == '/':
1823 regex = type_name[1:]
1824 if input_api.re.search(regex, line):
1825 matched = True
1826 elif type_name in line:
1827 matched = True
1828
1829 result = []
1830 if matched:
1831 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1832 for message_line in message:
1833 result.append(' %s' % message_line)
1834
1835 return result
1836
1837
[email protected]127f18ec2012-06-16 05:05:591838def _CheckNoBannedFunctions(input_api, output_api):
1839 """Make sure that banned functions are not used."""
1840 warnings = []
1841 errors = []
1842
wnwenbdc444e2016-05-25 13:44:151843 def IsBlacklisted(affected_file, blacklist):
1844 local_path = affected_file.LocalPath()
1845 for item in blacklist:
1846 if input_api.re.match(item, local_path):
1847 return True
1848 return False
1849
Peter K. Lee6c03ccff2019-07-15 14:40:051850 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541851 local_path = affected_file.LocalPath()
1852 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1853 return False
1854 basename = input_api.os_path.basename(local_path)
1855 if 'ios' in basename.split('_'):
1856 return True
1857 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1858 if sep and 'ios' in local_path.split(sep):
1859 return True
1860 return False
1861
wnwenbdc444e2016-05-25 13:44:151862 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311863 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1864 func_name, message)
1865 if problems:
wnwenbdc444e2016-05-25 13:44:151866 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311867 errors.extend(problems)
1868 else:
1869 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151870
Eric Stevensona9a980972017-09-23 00:04:411871 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1872 for f in input_api.AffectedFiles(file_filter=file_filter):
1873 for line_num, line in f.ChangedContents():
1874 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1875 CheckForMatch(f, line_num, line, func_name, message, error)
1876
[email protected]127f18ec2012-06-16 05:05:591877 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1878 for f in input_api.AffectedFiles(file_filter=file_filter):
1879 for line_num, line in f.ChangedContents():
1880 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151881 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591882
Peter K. Lee6c03ccff2019-07-15 14:40:051883 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541884 for line_num, line in f.ChangedContents():
1885 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1886 CheckForMatch(f, line_num, line, func_name, message, error)
1887
Peter K. Lee6c03ccff2019-07-15 14:40:051888 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1889 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1890 for line_num, line in f.ChangedContents():
1891 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1892 CheckForMatch(f, line_num, line, func_name, message, error)
1893
[email protected]127f18ec2012-06-16 05:05:591894 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1895 for f in input_api.AffectedFiles(file_filter=file_filter):
1896 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491897 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491898 if IsBlacklisted(f, excluded_paths):
1899 continue
wnwenbdc444e2016-05-25 13:44:151900 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591901
1902 result = []
1903 if (warnings):
1904 result.append(output_api.PresubmitPromptWarning(
1905 'Banned functions were used.\n' + '\n'.join(warnings)))
1906 if (errors):
1907 result.append(output_api.PresubmitError(
1908 'Banned functions were used.\n' + '\n'.join(errors)))
1909 return result
1910
1911
Michael Thiessen44457642020-02-06 00:24:151912def _CheckAndroidNoBannedImports(input_api, output_api):
1913 """Make sure that banned java imports are not used."""
1914 errors = []
1915
1916 def IsException(path, exceptions):
1917 for exception in exceptions:
1918 if (path.startswith(exception)):
1919 return True
1920 return False
1921
1922 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1923 for f in input_api.AffectedFiles(file_filter=file_filter):
1924 for line_num, line in f.ChangedContents():
1925 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1926 if IsException(f.LocalPath(), exceptions):
1927 continue;
1928 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1929 'import ' + import_name, message)
1930 if problems:
1931 errors.extend(problems)
1932 result = []
1933 if (errors):
1934 result.append(output_api.PresubmitError(
1935 'Banned imports were used.\n' + '\n'.join(errors)))
1936 return result
1937
1938
Mario Sanchez Prada2472cab2019-09-18 10:58:311939def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1940 """Make sure that old Mojo types are not used."""
1941 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571942 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311943
Mario Sanchez Pradaaab91382019-12-19 08:57:091944 # For any path that is not an "ok" or an "error" path, a warning will be
1945 # raised if deprecated mojo types are found.
1946 ok_paths = ['components/arc']
1947 error_paths = ['third_party/blink', 'content']
1948
Mario Sanchez Prada2472cab2019-09-18 10:58:311949 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1950 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571951 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091952 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311953 continue
1954
1955 for line_num, line in f.ChangedContents():
1956 for func_name, message in _DEPRECATED_MOJO_TYPES:
1957 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1958 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571959
Mario Sanchez Prada2472cab2019-09-18 10:58:311960 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091961 # Raise errors inside |error_paths| and warnings everywhere else.
1962 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571963 errors.extend(problems)
1964 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311965 warnings.extend(problems)
1966
1967 result = []
1968 if (warnings):
1969 result.append(output_api.PresubmitPromptWarning(
1970 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571971 if (errors):
1972 result.append(output_api.PresubmitError(
1973 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311974 return result
1975
1976
[email protected]6c063c62012-07-11 19:11:061977def _CheckNoPragmaOnce(input_api, output_api):
1978 """Make sure that banned functions are not used."""
1979 files = []
1980 pattern = input_api.re.compile(r'^#pragma\s+once',
1981 input_api.re.MULTILINE)
1982 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1983 if not f.LocalPath().endswith('.h'):
1984 continue
1985 contents = input_api.ReadFile(f)
1986 if pattern.search(contents):
1987 files.append(f)
1988
1989 if files:
1990 return [output_api.PresubmitError(
1991 'Do not use #pragma once in header files.\n'
1992 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1993 files)]
1994 return []
1995
[email protected]127f18ec2012-06-16 05:05:591996
[email protected]e7479052012-09-19 00:26:121997def _CheckNoTrinaryTrueFalse(input_api, output_api):
1998 """Checks to make sure we don't introduce use of foo ? true : false."""
1999 problems = []
2000 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
2001 for f in input_api.AffectedFiles():
2002 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2003 continue
2004
2005 for line_num, line in f.ChangedContents():
2006 if pattern.match(line):
2007 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2008
2009 if not problems:
2010 return []
2011 return [output_api.PresubmitPromptWarning(
2012 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2013 '\n'.join(problems))]
2014
2015
[email protected]55f9f382012-07-31 11:02:182016def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282017 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182018 change. Breaking - rules is an error, breaking ! rules is a
2019 warning.
2020 """
mohan.reddyf21db962014-10-16 12:26:472021 import sys
[email protected]55f9f382012-07-31 11:02:182022 # We need to wait until we have an input_api object and use this
2023 # roundabout construct to import checkdeps because this file is
2024 # eval-ed and thus doesn't have __file__.
2025 original_sys_path = sys.path
2026 try:
2027 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472028 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182029 import checkdeps
[email protected]55f9f382012-07-31 11:02:182030 from rules import Rule
2031 finally:
2032 # Restore sys.path to what it was before.
2033 sys.path = original_sys_path
2034
2035 added_includes = []
rhalavati08acd232017-04-03 07:23:282036 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242037 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182038 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062039 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502040 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082041 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062042 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502043 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082044 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062045 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502046 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082047 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182048
[email protected]26385172013-05-09 23:11:352049 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182050
2051 error_descriptions = []
2052 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282053 error_subjects = set()
2054 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182055 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2056 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082057 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182058 description_with_path = '%s\n %s' % (path, rule_description)
2059 if rule_type == Rule.DISALLOW:
2060 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282061 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182062 else:
2063 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282064 warning_subjects.add("#includes")
2065
2066 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2067 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082068 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282069 description_with_path = '%s\n %s' % (path, rule_description)
2070 if rule_type == Rule.DISALLOW:
2071 error_descriptions.append(description_with_path)
2072 error_subjects.add("imports")
2073 else:
2074 warning_descriptions.append(description_with_path)
2075 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182076
Jinsuk Kim5a092672017-10-24 22:42:242077 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022078 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082079 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242080 description_with_path = '%s\n %s' % (path, rule_description)
2081 if rule_type == Rule.DISALLOW:
2082 error_descriptions.append(description_with_path)
2083 error_subjects.add("imports")
2084 else:
2085 warning_descriptions.append(description_with_path)
2086 warning_subjects.add("imports")
2087
[email protected]55f9f382012-07-31 11:02:182088 results = []
2089 if error_descriptions:
2090 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282091 'You added one or more %s that violate checkdeps rules.'
2092 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182093 error_descriptions))
2094 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422095 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282096 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182097 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282098 '%s? See relevant DEPS file(s) for details and contacts.' %
2099 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182100 warning_descriptions))
2101 return results
2102
2103
[email protected]fbcafe5a2012-08-08 15:31:222104def _CheckFilePermissions(input_api, output_api):
2105 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152106 if input_api.platform == 'win32':
2107 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292108 checkperms_tool = input_api.os_path.join(
2109 input_api.PresubmitLocalPath(),
2110 'tools', 'checkperms', 'checkperms.py')
2111 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472112 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392113 with input_api.CreateTemporaryFile() as file_list:
2114 for f in input_api.AffectedFiles():
2115 # checkperms.py file/directory arguments must be relative to the
2116 # repository.
2117 file_list.write(f.LocalPath() + '\n')
2118 file_list.close()
2119 args += ['--file-list', file_list.name]
2120 try:
2121 input_api.subprocess.check_output(args)
2122 return []
2123 except input_api.subprocess.CalledProcessError as error:
2124 return [output_api.PresubmitError(
2125 'checkperms.py failed:',
2126 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222127
2128
robertocn832f5992017-01-04 19:01:302129def _CheckTeamTags(input_api, output_api):
2130 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2131 checkteamtags_tool = input_api.os_path.join(
2132 input_api.PresubmitLocalPath(),
2133 'tools', 'checkteamtags', 'checkteamtags.py')
2134 args = [input_api.python_executable, checkteamtags_tool,
2135 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222136 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302137 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2138 'OWNERS']
2139 try:
2140 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052141 warnings = input_api.subprocess.check_output(args + files).splitlines()
2142 if warnings:
2143 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302144 return []
2145 except input_api.subprocess.CalledProcessError as error:
2146 return [output_api.PresubmitError(
2147 'checkteamtags.py failed:',
2148 long_text=error.output)]
2149
2150
[email protected]c8278b32012-10-30 20:35:492151def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2152 """Makes sure we don't include ui/aura/window_property.h
2153 in header files.
2154 """
2155 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2156 errors = []
2157 for f in input_api.AffectedFiles():
2158 if not f.LocalPath().endswith('.h'):
2159 continue
2160 for line_num, line in f.ChangedContents():
2161 if pattern.match(line):
2162 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2163
2164 results = []
2165 if errors:
2166 results.append(output_api.PresubmitError(
2167 'Header files should not include ui/aura/window_property.h', errors))
2168 return results
2169
2170
[email protected]70ca77752012-11-20 03:45:032171def _CheckForVersionControlConflictsInFile(input_api, f):
2172 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2173 errors = []
2174 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162175 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232176 # First-level headers in markdown look a lot like version control
2177 # conflict markers. http://daringfireball.net/projects/markdown/basics
2178 continue
[email protected]70ca77752012-11-20 03:45:032179 if pattern.match(line):
2180 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2181 return errors
2182
2183
2184def _CheckForVersionControlConflicts(input_api, output_api):
2185 """Usually this is not intentional and will cause a compile failure."""
2186 errors = []
2187 for f in input_api.AffectedFiles():
2188 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2189
2190 results = []
2191 if errors:
2192 results.append(output_api.PresubmitError(
2193 'Version control conflict markers found, please resolve.', errors))
2194 return results
2195
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202196
estadee17314a02017-01-12 16:22:162197def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2198 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2199 errors = []
2200 for f in input_api.AffectedFiles():
2201 for line_num, line in f.ChangedContents():
2202 if pattern.search(line):
2203 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2204
2205 results = []
2206 if errors:
2207 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502208 'Found Google support URL addressed by answer number. Please replace '
2209 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162210 return results
2211
[email protected]70ca77752012-11-20 03:45:032212
[email protected]06e6d0ff2012-12-11 01:36:442213def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2214 def FilterFile(affected_file):
2215 """Filter function for use with input_api.AffectedSourceFiles,
2216 below. This filters out everything except non-test files from
2217 top-level directories that generally speaking should not hard-code
2218 service URLs (e.g. src/android_webview/, src/content/ and others).
2219 """
2220 return input_api.FilterSourceFile(
2221 affected_file,
Egor Paskoce145c42018-09-28 19:31:042222 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442223 black_list=(_EXCLUDED_PATHS +
2224 _TEST_CODE_EXCLUDED_PATHS +
2225 input_api.DEFAULT_BLACK_LIST))
2226
reillyi38965732015-11-16 18:27:332227 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2228 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462229 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2230 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442231 problems = [] # items are (filename, line_number, line)
2232 for f in input_api.AffectedSourceFiles(FilterFile):
2233 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462234 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442235 problems.append((f.LocalPath(), line_num, line))
2236
2237 if problems:
[email protected]f7051d52013-04-02 18:31:422238 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442239 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582240 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442241 [' %s:%d: %s' % (
2242 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032243 else:
2244 return []
[email protected]06e6d0ff2012-12-11 01:36:442245
2246
James Cook6b6597c2019-11-06 22:05:292247def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2248 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2249 def FileFilter(affected_file):
2250 """Includes directories known to be Chrome OS only."""
2251 return input_api.FilterSourceFile(
2252 affected_file,
2253 white_list=('^ash/',
2254 '^chromeos/', # Top-level src/chromeos.
2255 '/chromeos/', # Any path component.
2256 '^components/arc',
2257 '^components/exo'),
2258 black_list=(input_api.DEFAULT_BLACK_LIST))
2259
2260 prefs = []
2261 priority_prefs = []
2262 for f in input_api.AffectedFiles(file_filter=FileFilter):
2263 for line_num, line in f.ChangedContents():
2264 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2265 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2266 prefs.append(' %s' % line)
2267 if input_api.re.search(
2268 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2269 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2270 priority_prefs.append(' %s' % line)
2271
2272 results = []
2273 if (prefs):
2274 results.append(output_api.PresubmitPromptWarning(
2275 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2276 'by browser sync settings. If these prefs should be controlled by OS '
2277 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2278 if (priority_prefs):
2279 results.append(output_api.PresubmitPromptWarning(
2280 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2281 'controlled by browser sync settings. If these prefs should be '
2282 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2283 'instead.\n' + '\n'.join(prefs)))
2284 return results
2285
2286
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492287# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272288def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2289 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312290 The native_client_sdk directory is excluded because it has auto-generated PNG
2291 files for documentation.
[email protected]d2530012013-01-25 16:39:272292 """
[email protected]d2530012013-01-25 16:39:272293 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492294 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042295 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312296 file_filter = lambda f: input_api.FilterSourceFile(
2297 f, white_list=white_list, black_list=black_list)
2298 for f in input_api.AffectedFiles(include_deletes=False,
2299 file_filter=file_filter):
2300 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272301
2302 results = []
2303 if errors:
2304 results.append(output_api.PresubmitError(
2305 'The name of PNG files should not have abbreviations. \n'
2306 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2307 'Contact [email protected] if you have questions.', errors))
2308 return results
2309
2310
Daniel Cheng4dcdb6b2017-04-13 08:30:172311def _ExtractAddRulesFromParsedDeps(parsed_deps):
2312 """Extract the rules that add dependencies from a parsed DEPS file.
2313
2314 Args:
2315 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2316 add_rules = set()
2317 add_rules.update([
2318 rule[1:] for rule in parsed_deps.get('include_rules', [])
2319 if rule.startswith('+') or rule.startswith('!')
2320 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502321 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172322 {}).iteritems():
2323 add_rules.update([
2324 rule[1:] for rule in rules
2325 if rule.startswith('+') or rule.startswith('!')
2326 ])
2327 return add_rules
2328
2329
2330def _ParseDeps(contents):
2331 """Simple helper for parsing DEPS files."""
2332 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172333 class _VarImpl:
2334
2335 def __init__(self, local_scope):
2336 self._local_scope = local_scope
2337
2338 def Lookup(self, var_name):
2339 """Implements the Var syntax."""
2340 try:
2341 return self._local_scope['vars'][var_name]
2342 except KeyError:
2343 raise Exception('Var is not defined: %s' % var_name)
2344
2345 local_scope = {}
2346 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172347 'Var': _VarImpl(local_scope).Lookup,
2348 }
2349 exec contents in global_scope, local_scope
2350 return local_scope
2351
2352
2353def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082354 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412355 a set of DEPS entries that we should look up.
2356
2357 For a directory (rather than a specific filename) we fake a path to
2358 a specific filename by adding /DEPS. This is chosen as a file that
2359 will seldom or never be subject to per-file include_rules.
2360 """
[email protected]2b438d62013-11-14 17:54:142361 # We ignore deps entries on auto-generated directories.
2362 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082363
Daniel Cheng4dcdb6b2017-04-13 08:30:172364 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2365 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2366
2367 added_deps = new_deps.difference(old_deps)
2368
[email protected]2b438d62013-11-14 17:54:142369 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172370 for added_dep in added_deps:
2371 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2372 continue
2373 # Assume that a rule that ends in .h is a rule for a specific file.
2374 if added_dep.endswith('.h'):
2375 results.add(added_dep)
2376 else:
2377 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082378 return results
2379
2380
[email protected]e871964c2013-05-13 14:14:552381def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2382 """When a dependency prefixed with + is added to a DEPS file, we
2383 want to make sure that the change is reviewed by an OWNER of the
2384 target file or directory, to avoid layering violations from being
2385 introduced. This check verifies that this happens.
2386 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172387 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242388
2389 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492390 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242391 for f in input_api.AffectedFiles(include_deletes=False,
2392 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552393 filename = input_api.os_path.basename(f.LocalPath())
2394 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172395 virtual_depended_on_files.update(_CalculateAddedDeps(
2396 input_api.os_path,
2397 '\n'.join(f.OldContents()),
2398 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552399
[email protected]e871964c2013-05-13 14:14:552400 if not virtual_depended_on_files:
2401 return []
2402
2403 if input_api.is_committing:
2404 if input_api.tbr:
2405 return [output_api.PresubmitNotifyResult(
2406 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272407 if input_api.dry_run:
2408 return [output_api.PresubmitNotifyResult(
2409 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552410 if not input_api.change.issue:
2411 return [output_api.PresubmitError(
2412 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402413 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552414 output = output_api.PresubmitError
2415 else:
2416 output = output_api.PresubmitNotifyResult
2417
2418 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502419 owner_email, reviewers = (
2420 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2421 input_api,
2422 owners_db.email_regexp,
2423 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552424
2425 owner_email = owner_email or input_api.change.author_email
2426
[email protected]de4f7d22013-05-23 14:27:462427 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512428 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462429 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552430 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2431 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412432
2433 # We strip the /DEPS part that was added by
2434 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2435 # directory.
2436 def StripDeps(path):
2437 start_deps = path.rfind('/DEPS')
2438 if start_deps != -1:
2439 return path[:start_deps]
2440 else:
2441 return path
2442 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552443 for path in missing_files]
2444
2445 if unapproved_dependencies:
2446 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152447 output('You need LGTM from owners of depends-on paths in DEPS that were '
2448 'modified in this CL:\n %s' %
2449 '\n '.join(sorted(unapproved_dependencies)))]
2450 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2451 output_list.append(output(
2452 'Suggested missing target path OWNERS:\n %s' %
2453 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552454 return output_list
2455
2456 return []
2457
2458
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492459# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402460def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492461 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402462 black_list = (_EXCLUDED_PATHS +
2463 _TEST_CODE_EXCLUDED_PATHS +
2464 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042465 (r"^base[\\/]logging\.h$",
2466 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222467 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042468 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2469 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2470 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122471 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182472 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152473 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032474 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152475 r"^chrome[\\/]chrome_cleaner[\\/].*",
2476 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2477 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042478 r"^chromecast[\\/]",
2479 r"^cloud_print[\\/]",
2480 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482481 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042482 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312483 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042484 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462485 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042486 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462487 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042488 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252489 r"gl_helper_benchmark\.cc$",
Robert Flackc0ee0272020-02-26 05:57:402490 r"^content[\\/]renderer[\\/]render_frame_impl.cc$",
Egor Paskoce145c42018-09-28 19:31:042491 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2492 r"^courgette[\\/]courgette_tool\.cc$",
2493 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272494 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002495 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332496 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042497 r"^ipc[\\/]ipc_logging\.cc$",
2498 r"^native_client_sdk[\\/]",
2499 r"^remoting[\\/]base[\\/]logging\.h$",
2500 r"^remoting[\\/]host[\\/].*",
2501 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062502 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332503 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042504 r"^tools[\\/]",
2505 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2506 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332507 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402508 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492509 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402510
thomasanderson625d3932017-03-29 07:16:582511 log_info = set([])
2512 printf = set([])
[email protected]85218562013-11-22 07:41:402513
2514 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582515 for _, line in f.ChangedContents():
2516 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2517 log_info.add(f.LocalPath())
2518 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2519 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372520
thomasanderson625d3932017-03-29 07:16:582521 if input_api.re.search(r"\bprintf\(", line):
2522 printf.add(f.LocalPath())
2523 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2524 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402525
2526 if log_info:
2527 return [output_api.PresubmitError(
2528 'These files spam the console log with LOG(INFO):',
2529 items=log_info)]
2530 if printf:
2531 return [output_api.PresubmitError(
2532 'These files spam the console log with printf/fprintf:',
2533 items=printf)]
2534 return []
2535
2536
[email protected]49aa76a2013-12-04 06:59:162537def _CheckForAnonymousVariables(input_api, output_api):
2538 """These types are all expected to hold locks while in scope and
2539 so should never be anonymous (which causes them to be immediately
2540 destroyed)."""
2541 they_who_must_be_named = [
2542 'base::AutoLock',
2543 'base::AutoReset',
2544 'base::AutoUnlock',
2545 'SkAutoAlphaRestore',
2546 'SkAutoBitmapShaderInstall',
2547 'SkAutoBlitterChoose',
2548 'SkAutoBounderCommit',
2549 'SkAutoCallProc',
2550 'SkAutoCanvasRestore',
2551 'SkAutoCommentBlock',
2552 'SkAutoDescriptor',
2553 'SkAutoDisableDirectionCheck',
2554 'SkAutoDisableOvalCheck',
2555 'SkAutoFree',
2556 'SkAutoGlyphCache',
2557 'SkAutoHDC',
2558 'SkAutoLockColors',
2559 'SkAutoLockPixels',
2560 'SkAutoMalloc',
2561 'SkAutoMaskFreeImage',
2562 'SkAutoMutexAcquire',
2563 'SkAutoPathBoundsUpdate',
2564 'SkAutoPDFRelease',
2565 'SkAutoRasterClipValidate',
2566 'SkAutoRef',
2567 'SkAutoTime',
2568 'SkAutoTrace',
2569 'SkAutoUnref',
2570 ]
2571 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2572 # bad: base::AutoLock(lock.get());
2573 # not bad: base::AutoLock lock(lock.get());
2574 bad_pattern = input_api.re.compile(anonymous)
2575 # good: new base::AutoLock(lock.get())
2576 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2577 errors = []
2578
2579 for f in input_api.AffectedFiles():
2580 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2581 continue
2582 for linenum, line in f.ChangedContents():
2583 if bad_pattern.search(line) and not good_pattern.search(line):
2584 errors.append('%s:%d' % (f.LocalPath(), linenum))
2585
2586 if errors:
2587 return [output_api.PresubmitError(
2588 'These lines create anonymous variables that need to be named:',
2589 items=errors)]
2590 return []
2591
2592
Peter Kasting4844e46e2018-02-23 07:27:102593def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532594 # Returns whether |template_str| is of the form <T, U...> for some types T
2595 # and U. Assumes that |template_str| is already in the form <...>.
2596 def HasMoreThanOneArg(template_str):
2597 # Level of <...> nesting.
2598 nesting = 0
2599 for c in template_str:
2600 if c == '<':
2601 nesting += 1
2602 elif c == '>':
2603 nesting -= 1
2604 elif c == ',' and nesting == 1:
2605 return True
2606 return False
2607
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492608 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102609 sources = lambda affected_file: input_api.FilterSourceFile(
2610 affected_file,
2611 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2612 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492613 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552614
2615 # Pattern to capture a single "<...>" block of template arguments. It can
2616 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2617 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2618 # latter would likely require counting that < and > match, which is not
2619 # expressible in regular languages. Should the need arise, one can introduce
2620 # limited counting (matching up to a total number of nesting depth), which
2621 # should cover all practical cases for already a low nesting limit.
2622 template_arg_pattern = (
2623 r'<[^>]*' # Opening block of <.
2624 r'>([^<]*>)?') # Closing block of >.
2625 # Prefix expressing that whatever follows is not already inside a <...>
2626 # block.
2627 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102628 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552629 not_inside_template_arg_pattern
2630 + r'\bstd::unique_ptr'
2631 + template_arg_pattern
2632 + r'\(\)')
2633
2634 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2635 template_arg_no_array_pattern = (
2636 r'<[^>]*[^]]' # Opening block of <.
2637 r'>([^(<]*[^]]>)?') # Closing block of >.
2638 # Prefix saying that what follows is the start of an expression.
2639 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2640 # Suffix saying that what follows are call parentheses with a non-empty list
2641 # of arguments.
2642 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532643 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552644 return_construct_pattern = input_api.re.compile(
2645 start_of_expr_pattern
2646 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532647 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552648 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532649 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552650 + nonempty_arg_list_pattern)
2651
Vaclav Brozek851d9602018-04-04 16:13:052652 problems_constructor = []
2653 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102654 for f in input_api.AffectedSourceFiles(sources):
2655 for line_number, line in f.ChangedContents():
2656 # Disallow:
2657 # return std::unique_ptr<T>(foo);
2658 # bar = std::unique_ptr<T>(foo);
2659 # But allow:
2660 # return std::unique_ptr<T[]>(foo);
2661 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532662 # And also allow cases when the second template argument is present. Those
2663 # cases cannot be handled by std::make_unique:
2664 # return std::unique_ptr<T, U>(foo);
2665 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052666 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532667 return_construct_result = return_construct_pattern.search(line)
2668 if return_construct_result and not HasMoreThanOneArg(
2669 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052670 problems_constructor.append(
2671 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102672 # Disallow:
2673 # std::unique_ptr<T>()
2674 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052675 problems_nullptr.append(
2676 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2677
2678 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162679 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052680 errors.append(output_api.PresubmitError(
2681 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162682 problems_nullptr))
2683 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052684 errors.append(output_api.PresubmitError(
2685 'The following files use explicit std::unique_ptr constructor.'
2686 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162687 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102688 return errors
2689
2690
[email protected]999261d2014-03-03 20:08:082691def _CheckUserActionUpdate(input_api, output_api):
2692 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522693 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082694 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522695 # If actions.xml is already included in the changelist, the PRESUBMIT
2696 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082697 return []
2698
[email protected]999261d2014-03-03 20:08:082699 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2700 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522701 current_actions = None
[email protected]999261d2014-03-03 20:08:082702 for f in input_api.AffectedFiles(file_filter=file_filter):
2703 for line_num, line in f.ChangedContents():
2704 match = input_api.re.search(action_re, line)
2705 if match:
[email protected]2f92dec2014-03-07 19:21:522706 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2707 # loaded only once.
2708 if not current_actions:
2709 with open('tools/metrics/actions/actions.xml') as actions_f:
2710 current_actions = actions_f.read()
2711 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082712 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522713 action = 'name="{0}"'.format(action_name)
2714 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082715 return [output_api.PresubmitPromptWarning(
2716 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522717 'tools/metrics/actions/actions.xml. Please run '
2718 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082719 % (f.LocalPath(), line_num, action_name))]
2720 return []
2721
2722
Daniel Cheng13ca61a882017-08-25 15:11:252723def _ImportJSONCommentEater(input_api):
2724 import sys
2725 sys.path = sys.path + [input_api.os_path.join(
2726 input_api.PresubmitLocalPath(),
2727 'tools', 'json_comment_eater')]
2728 import json_comment_eater
2729 return json_comment_eater
2730
2731
[email protected]99171a92014-06-03 08:44:472732def _GetJSONParseError(input_api, filename, eat_comments=True):
2733 try:
2734 contents = input_api.ReadFile(filename)
2735 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252736 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132737 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472738
2739 input_api.json.loads(contents)
2740 except ValueError as e:
2741 return e
2742 return None
2743
2744
2745def _GetIDLParseError(input_api, filename):
2746 try:
2747 contents = input_api.ReadFile(filename)
2748 idl_schema = input_api.os_path.join(
2749 input_api.PresubmitLocalPath(),
2750 'tools', 'json_schema_compiler', 'idl_schema.py')
2751 process = input_api.subprocess.Popen(
2752 [input_api.python_executable, idl_schema],
2753 stdin=input_api.subprocess.PIPE,
2754 stdout=input_api.subprocess.PIPE,
2755 stderr=input_api.subprocess.PIPE,
2756 universal_newlines=True)
2757 (_, error) = process.communicate(input=contents)
2758 return error or None
2759 except ValueError as e:
2760 return e
2761
2762
2763def _CheckParseErrors(input_api, output_api):
2764 """Check that IDL and JSON files do not contain syntax errors."""
2765 actions = {
2766 '.idl': _GetIDLParseError,
2767 '.json': _GetJSONParseError,
2768 }
[email protected]99171a92014-06-03 08:44:472769 # Most JSON files are preprocessed and support comments, but these do not.
2770 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042771 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472772 ]
2773 # Only run IDL checker on files in these directories.
2774 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042775 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2776 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472777 ]
2778
2779 def get_action(affected_file):
2780 filename = affected_file.LocalPath()
2781 return actions.get(input_api.os_path.splitext(filename)[1])
2782
[email protected]99171a92014-06-03 08:44:472783 def FilterFile(affected_file):
2784 action = get_action(affected_file)
2785 if not action:
2786 return False
2787 path = affected_file.LocalPath()
2788
Sean Kau46e29bc2017-08-28 16:31:162789 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472790 return False
2791
2792 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162793 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472794 return False
2795 return True
2796
2797 results = []
2798 for affected_file in input_api.AffectedFiles(
2799 file_filter=FilterFile, include_deletes=False):
2800 action = get_action(affected_file)
2801 kwargs = {}
2802 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162803 _MatchesFile(input_api, json_no_comments_patterns,
2804 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472805 kwargs['eat_comments'] = False
2806 parse_error = action(input_api,
2807 affected_file.AbsoluteLocalPath(),
2808 **kwargs)
2809 if parse_error:
2810 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2811 (affected_file.LocalPath(), parse_error)))
2812 return results
2813
2814
[email protected]760deea2013-12-10 19:33:492815def _CheckJavaStyle(input_api, output_api):
2816 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472817 import sys
[email protected]760deea2013-12-10 19:33:492818 original_sys_path = sys.path
2819 try:
2820 sys.path = sys.path + [input_api.os_path.join(
2821 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2822 import checkstyle
2823 finally:
2824 # Restore sys.path to what it was before.
2825 sys.path = original_sys_path
2826
2827 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092828 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512829 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492830
2831
Nate Fischerdfd9812e2019-07-18 22:03:002832def _CheckPythonDevilInit(input_api, output_api):
2833 """Checks to make sure devil is initialized correctly in python scripts."""
2834 script_common_initialize_pattern = input_api.re.compile(
2835 r'script_common\.InitializeEnvironment\(')
2836 devil_env_config_initialize = input_api.re.compile(
2837 r'devil_env\.config\.Initialize\(')
2838
2839 errors = []
2840
2841 sources = lambda affected_file: input_api.FilterSourceFile(
2842 affected_file,
2843 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2844 (r'^build[\\/]android[\\/]devil_chromium\.py',
2845 r'^third_party[\\/].*',)),
2846 white_list=[r'.*\.py$'])
2847
2848 for f in input_api.AffectedSourceFiles(sources):
2849 for line_num, line in f.ChangedContents():
2850 if (script_common_initialize_pattern.search(line) or
2851 devil_env_config_initialize.search(line)):
2852 errors.append("%s:%d" % (f.LocalPath(), line_num))
2853
2854 results = []
2855
2856 if errors:
2857 results.append(output_api.PresubmitError(
2858 'Devil initialization should always be done using '
2859 'devil_chromium.Initialize() in the chromium project, to use better '
2860 'defaults for dependencies (ex. up-to-date version of adb).',
2861 errors))
2862
2863 return results
2864
2865
Sean Kau46e29bc2017-08-28 16:31:162866def _MatchesFile(input_api, patterns, path):
2867 for pattern in patterns:
2868 if input_api.re.search(pattern, path):
2869 return True
2870 return False
2871
2872
Daniel Cheng7052cdf2017-11-21 19:23:292873def _GetOwnersFilesToCheckForIpcOwners(input_api):
2874 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172875
Daniel Cheng7052cdf2017-11-21 19:23:292876 Returns:
2877 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2878 contain to cover IPC-related files with noparent reviewer rules.
2879 """
2880 # Whether or not a file affects IPC is (mostly) determined by a simple list
2881 # of filename patterns.
dchenge07de812016-06-20 19:27:172882 file_patterns = [
palmerb19a0932017-01-24 04:00:312883 # Legacy IPC:
dchenge07de812016-06-20 19:27:172884 '*_messages.cc',
2885 '*_messages*.h',
2886 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312887 # Mojo IPC:
dchenge07de812016-06-20 19:27:172888 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472889 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172890 '*_struct_traits*.*',
2891 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312892 '*.typemap',
2893 # Android native IPC:
2894 '*.aidl',
2895 # Blink uses a different file naming convention:
2896 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472897 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172898 '*StructTraits*.*',
2899 '*TypeConverter*.*',
2900 ]
2901
scottmg7a6ed5ba2016-11-04 18:22:042902 # These third_party directories do not contain IPCs, but contain files
2903 # matching the above patterns, which trigger false positives.
2904 exclude_paths = [
2905 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162906 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232907 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292908 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542909 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162910 # These files are just used to communicate between class loaders running
2911 # in the same process.
2912 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572913 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2914
scottmg7a6ed5ba2016-11-04 18:22:042915 ]
2916
dchenge07de812016-06-20 19:27:172917 # Dictionary mapping an OWNERS file path to Patterns.
2918 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2919 # rules ) to a PatternEntry.
2920 # PatternEntry is a dictionary with two keys:
2921 # - 'files': the files that are matched by this pattern
2922 # - 'rules': the per-file rules needed for this pattern
2923 # For example, if we expect OWNERS file to contain rules for *.mojom and
2924 # *_struct_traits*.*, Patterns might look like this:
2925 # {
2926 # '*.mojom': {
2927 # 'files': ...,
2928 # 'rules': [
2929 # 'per-file *.mojom=set noparent',
2930 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2931 # ],
2932 # },
2933 # '*_struct_traits*.*': {
2934 # 'files': ...,
2935 # 'rules': [
2936 # 'per-file *_struct_traits*.*=set noparent',
2937 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2938 # ],
2939 # },
2940 # }
2941 to_check = {}
2942
Daniel Cheng13ca61a882017-08-25 15:11:252943 def AddPatternToCheck(input_file, pattern):
2944 owners_file = input_api.os_path.join(
2945 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2946 if owners_file not in to_check:
2947 to_check[owners_file] = {}
2948 if pattern not in to_check[owners_file]:
2949 to_check[owners_file][pattern] = {
2950 'files': [],
2951 'rules': [
2952 'per-file %s=set noparent' % pattern,
2953 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2954 ]
2955 }
Vaclav Brozekd5de76a2018-03-17 07:57:502956 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252957
dchenge07de812016-06-20 19:27:172958 # Iterate through the affected files to see what we actually need to check
2959 # for. We should only nag patch authors about per-file rules if a file in that
2960 # directory would match that pattern. If a directory only contains *.mojom
2961 # files and no *_messages*.h files, we should only nag about rules for
2962 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252963 for f in input_api.AffectedFiles(include_deletes=False):
2964 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362965 # affected files for .json, .cc, and .h files which look like they contain
2966 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162967 if (f.LocalPath().endswith('.json') and
2968 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2969 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252970 json_comment_eater = _ImportJSONCommentEater(input_api)
2971 mostly_json_lines = '\n'.join(f.NewContents())
2972 # Comments aren't allowed in strict JSON, so filter them out.
2973 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432974 try:
2975 json_content = input_api.json.loads(json_lines)
2976 except:
2977 # There's another PRESUBMIT check that already verifies that JSON files
2978 # are not invalid, so no need to emit another warning here.
2979 continue
Daniel Cheng13ca61a882017-08-25 15:11:252980 if 'interface_provider_specs' in json_content:
2981 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362982 else:
2983 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2984 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2985 if (manifest_pattern.search(f.LocalPath()) and not
2986 test_manifest_pattern.search(f.LocalPath())):
2987 # We expect all actual service manifest files to contain at least one
2988 # qualified reference to service_manager::Manifest.
2989 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2990 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172991 for pattern in file_patterns:
2992 if input_api.fnmatch.fnmatch(
2993 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042994 skip = False
2995 for exclude in exclude_paths:
2996 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2997 skip = True
2998 break
2999 if skip:
3000 continue
Daniel Cheng13ca61a882017-08-25 15:11:253001 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:173002 break
3003
Daniel Cheng7052cdf2017-11-21 19:23:293004 return to_check
3005
3006
3007def _CheckIpcOwners(input_api, output_api):
3008 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3009 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
3010
3011 if to_check:
3012 # If there are any OWNERS files to check, there are IPC-related changes in
3013 # this CL. Auto-CC the review list.
3014 output_api.AppendCC('[email protected]')
3015
3016 # Go through the OWNERS files to check, filtering out rules that are already
3017 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173018 for owners_file, patterns in to_check.iteritems():
3019 try:
3020 with file(owners_file) as f:
3021 lines = set(f.read().splitlines())
3022 for entry in patterns.itervalues():
3023 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3024 ]
3025 except IOError:
3026 # No OWNERS file, so all the rules are definitely missing.
3027 continue
3028
3029 # All the remaining lines weren't found in OWNERS files, so emit an error.
3030 errors = []
3031 for owners_file, patterns in to_check.iteritems():
3032 missing_lines = []
3033 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503034 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173035 missing_lines.extend(entry['rules'])
3036 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3037 if missing_lines:
3038 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053039 'Because of the presence of files:\n%s\n\n'
3040 '%s needs the following %d lines added:\n\n%s' %
3041 ('\n'.join(files), owners_file, len(missing_lines),
3042 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173043
3044 results = []
3045 if errors:
vabrf5ce3bf92016-07-11 14:52:413046 if input_api.is_committing:
3047 output = output_api.PresubmitError
3048 else:
3049 output = output_api.PresubmitPromptWarning
3050 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593051 'Found OWNERS files that need to be updated for IPC security ' +
3052 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173053 long_text='\n\n'.join(errors)))
3054
3055 return results
3056
3057
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263058def _CheckSetNoParent(input_api, output_api):
3059 """Checks that set noparent is only used together with an OWNERS file in
3060 //build/OWNERS.setnoparent (see also
3061 //docs/code_reviews.md#owners-files-details)
3062 """
3063 errors = []
3064
3065 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3066 allowed_owners_files = set()
3067 with open(allowed_owners_files_file, 'r') as f:
3068 for line in f:
3069 line = line.strip()
3070 if not line or line.startswith('#'):
3071 continue
3072 allowed_owners_files.add(line)
3073
3074 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3075
3076 for f in input_api.AffectedFiles(include_deletes=False):
3077 if not f.LocalPath().endswith('OWNERS'):
3078 continue
3079
3080 found_owners_files = set()
3081 found_set_noparent_lines = dict()
3082
3083 # Parse the OWNERS file.
3084 for lineno, line in enumerate(f.NewContents(), 1):
3085 line = line.strip()
3086 if line.startswith('set noparent'):
3087 found_set_noparent_lines[''] = lineno
3088 if line.startswith('file://'):
3089 if line in allowed_owners_files:
3090 found_owners_files.add('')
3091 if line.startswith('per-file'):
3092 match = per_file_pattern.match(line)
3093 if match:
3094 glob = match.group(1).strip()
3095 directive = match.group(2).strip()
3096 if directive == 'set noparent':
3097 found_set_noparent_lines[glob] = lineno
3098 if directive.startswith('file://'):
3099 if directive in allowed_owners_files:
3100 found_owners_files.add(glob)
3101
3102 # Check that every set noparent line has a corresponding file:// line
3103 # listed in build/OWNERS.setnoparent.
3104 for set_noparent_line in found_set_noparent_lines:
3105 if set_noparent_line in found_owners_files:
3106 continue
3107 errors.append(' %s:%d' % (f.LocalPath(),
3108 found_set_noparent_lines[set_noparent_line]))
3109
3110 results = []
3111 if errors:
3112 if input_api.is_committing:
3113 output = output_api.PresubmitError
3114 else:
3115 output = output_api.PresubmitPromptWarning
3116 results.append(output(
3117 'Found the following "set noparent" restrictions in OWNERS files that '
3118 'do not include owners from build/OWNERS.setnoparent:',
3119 long_text='\n\n'.join(errors)))
3120 return results
3121
3122
jbriance9e12f162016-11-25 07:57:503123def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313124 """Checks that added or removed lines in non third party affected
3125 header files do not lead to new useless class or struct forward
3126 declaration.
jbriance9e12f162016-11-25 07:57:503127 """
3128 results = []
3129 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3130 input_api.re.MULTILINE)
3131 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3132 input_api.re.MULTILINE)
3133 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313134 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193135 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493136 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313137 continue
3138
jbriance9e12f162016-11-25 07:57:503139 if not f.LocalPath().endswith('.h'):
3140 continue
3141
3142 contents = input_api.ReadFile(f)
3143 fwd_decls = input_api.re.findall(class_pattern, contents)
3144 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3145
3146 useless_fwd_decls = []
3147 for decl in fwd_decls:
3148 count = sum(1 for _ in input_api.re.finditer(
3149 r'\b%s\b' % input_api.re.escape(decl), contents))
3150 if count == 1:
3151 useless_fwd_decls.append(decl)
3152
3153 if not useless_fwd_decls:
3154 continue
3155
3156 for line in f.GenerateScmDiff().splitlines():
3157 if (line.startswith('-') and not line.startswith('--') or
3158 line.startswith('+') and not line.startswith('++')):
3159 for decl in useless_fwd_decls:
3160 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3161 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243162 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503163 (f.LocalPath(), decl)))
3164 useless_fwd_decls.remove(decl)
3165
3166 return results
3167
Jinsong Fan91ebbbd2019-04-16 14:57:173168def _CheckAndroidDebuggableBuild(input_api, output_api):
3169 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3170 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3171 this is a debuggable build of Android.
3172 """
3173 build_type_check_pattern = input_api.re.compile(
3174 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3175
3176 errors = []
3177
3178 sources = lambda affected_file: input_api.FilterSourceFile(
3179 affected_file,
3180 black_list=(_EXCLUDED_PATHS +
3181 _TEST_CODE_EXCLUDED_PATHS +
3182 input_api.DEFAULT_BLACK_LIST +
3183 (r"^android_webview[\\/]support_library[\\/]"
3184 "boundary_interfaces[\\/]",
3185 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3186 r'^third_party[\\/].*',
3187 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3188 r"webview[\\/]chromium[\\/]License.*",)),
3189 white_list=[r'.*\.java$'])
3190
3191 for f in input_api.AffectedSourceFiles(sources):
3192 for line_num, line in f.ChangedContents():
3193 if build_type_check_pattern.search(line):
3194 errors.append("%s:%d" % (f.LocalPath(), line_num))
3195
3196 results = []
3197
3198 if errors:
3199 results.append(output_api.PresubmitPromptWarning(
3200 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3201 ' Please use BuildInfo.isDebugAndroid() instead.',
3202 errors))
3203
3204 return results
jbriance9e12f162016-11-25 07:57:503205
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493206# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293207def _CheckAndroidToastUsage(input_api, output_api):
3208 """Checks that code uses org.chromium.ui.widget.Toast instead of
3209 android.widget.Toast (Chromium Toast doesn't force hardware
3210 acceleration on low-end devices, saving memory).
3211 """
3212 toast_import_pattern = input_api.re.compile(
3213 r'^import android\.widget\.Toast;$')
3214
3215 errors = []
3216
3217 sources = lambda affected_file: input_api.FilterSourceFile(
3218 affected_file,
3219 black_list=(_EXCLUDED_PATHS +
3220 _TEST_CODE_EXCLUDED_PATHS +
3221 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043222 (r'^chromecast[\\/].*',
3223 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493224 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293225
3226 for f in input_api.AffectedSourceFiles(sources):
3227 for line_num, line in f.ChangedContents():
3228 if toast_import_pattern.search(line):
3229 errors.append("%s:%d" % (f.LocalPath(), line_num))
3230
3231 results = []
3232
3233 if errors:
3234 results.append(output_api.PresubmitError(
3235 'android.widget.Toast usage is detected. Android toasts use hardware'
3236 ' acceleration, and can be\ncostly on low-end devices. Please use'
3237 ' org.chromium.ui.widget.Toast instead.\n'
3238 'Contact [email protected] if you have any questions.',
3239 errors))
3240
3241 return results
3242
3243
dgnaa68d5e2015-06-10 10:08:223244def _CheckAndroidCrLogUsage(input_api, output_api):
3245 """Checks that new logs using org.chromium.base.Log:
3246 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513247 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223248 """
pkotwicza1dd0b002016-05-16 14:41:043249
torne89540622017-03-24 19:41:303250 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043251 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303252 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043253 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303254 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043255 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3256 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093257 # The customtabs_benchmark is a small app that does not depend on Chromium
3258 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043259 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043260 ]
3261
dgnaa68d5e2015-06-10 10:08:223262 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123263 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3264 class_in_base_pattern = input_api.re.compile(
3265 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3266 has_some_log_import_pattern = input_api.re.compile(
3267 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223268 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123269 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223270 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463271 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223272
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463273 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493274 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043275 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123276
dgnaa68d5e2015-06-10 10:08:223277 tag_decl_errors = []
3278 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123279 tag_errors = []
dgn38736db2015-09-18 19:20:513280 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123281 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223282
3283 for f in input_api.AffectedSourceFiles(sources):
3284 file_content = input_api.ReadFile(f)
3285 has_modified_logs = False
3286
3287 # Per line checks
dgn87d9fb62015-06-12 09:15:123288 if (cr_log_import_pattern.search(file_content) or
3289 (class_in_base_pattern.search(file_content) and
3290 not has_some_log_import_pattern.search(file_content))):
3291 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223292 for line_num, line in f.ChangedContents():
3293
3294 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123295 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223296 if match:
3297 has_modified_logs = True
3298
3299 # Make sure it uses "TAG"
3300 if not match.group('tag') == 'TAG':
3301 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123302 else:
3303 # Report non cr Log function calls in changed lines
3304 for line_num, line in f.ChangedContents():
3305 if log_call_pattern.search(line):
3306 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223307
3308 # Per file checks
3309 if has_modified_logs:
3310 # Make sure the tag is using the "cr" prefix and is not too long
3311 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513312 tag_name = match.group('name') if match else None
3313 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223314 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513315 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223316 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513317 elif '.' in tag_name:
3318 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223319
3320 results = []
3321 if tag_decl_errors:
3322 results.append(output_api.PresubmitPromptWarning(
3323 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513324 '"private static final String TAG = "<package tag>".\n'
3325 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223326 tag_decl_errors))
3327
3328 if tag_length_errors:
3329 results.append(output_api.PresubmitError(
3330 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513331 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223332 tag_length_errors))
3333
3334 if tag_errors:
3335 results.append(output_api.PresubmitPromptWarning(
3336 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3337 tag_errors))
3338
dgn87d9fb62015-06-12 09:15:123339 if util_log_errors:
dgn4401aa52015-04-29 16:26:173340 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123341 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3342 util_log_errors))
3343
dgn38736db2015-09-18 19:20:513344 if tag_with_dot_errors:
3345 results.append(output_api.PresubmitPromptWarning(
3346 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3347 tag_with_dot_errors))
3348
dgn4401aa52015-04-29 16:26:173349 return results
3350
3351
Yoland Yanb92fa522017-08-28 17:37:063352def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3353 """Checks that junit.framework.* is no longer used."""
3354 deprecated_junit_framework_pattern = input_api.re.compile(
3355 r'^import junit\.framework\..*;',
3356 input_api.re.MULTILINE)
3357 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493358 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063359 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133360 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063361 for line_num, line in f.ChangedContents():
3362 if deprecated_junit_framework_pattern.search(line):
3363 errors.append("%s:%d" % (f.LocalPath(), line_num))
3364
3365 results = []
3366 if errors:
3367 results.append(output_api.PresubmitError(
3368 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3369 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3370 ' if you have any question.', errors))
3371 return results
3372
3373
3374def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3375 """Checks that if new Java test classes have inheritance.
3376 Either the new test class is JUnit3 test or it is a JUnit4 test class
3377 with a base class, either case is undesirable.
3378 """
3379 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3380
3381 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493382 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063383 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133384 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063385 if not f.OldContents():
3386 class_declaration_start_flag = False
3387 for line_num, line in f.ChangedContents():
3388 if class_declaration_pattern.search(line):
3389 class_declaration_start_flag = True
3390 if class_declaration_start_flag and ' extends ' in line:
3391 errors.append('%s:%d' % (f.LocalPath(), line_num))
3392 if '{' in line:
3393 class_declaration_start_flag = False
3394
3395 results = []
3396 if errors:
3397 results.append(output_api.PresubmitPromptWarning(
3398 'The newly created files include Test classes that inherits from base'
3399 ' class. Please do not use inheritance in JUnit4 tests or add new'
3400 ' JUnit3 tests. Contact [email protected] if you have any'
3401 ' questions.', errors))
3402 return results
3403
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203404
yolandyan45001472016-12-21 21:12:423405def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3406 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3407 deprecated_annotation_import_pattern = input_api.re.compile(
3408 r'^import android\.test\.suitebuilder\.annotation\..*;',
3409 input_api.re.MULTILINE)
3410 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493411 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423412 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133413 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423414 for line_num, line in f.ChangedContents():
3415 if deprecated_annotation_import_pattern.search(line):
3416 errors.append("%s:%d" % (f.LocalPath(), line_num))
3417
3418 results = []
3419 if errors:
3420 results.append(output_api.PresubmitError(
3421 'Annotations in android.test.suitebuilder.annotation have been'
3422 ' deprecated since API level 24. Please use android.support.test.filters'
3423 ' from //third_party/android_support_test_runner:runner_java instead.'
3424 ' Contact [email protected] if you have any questions.', errors))
3425 return results
3426
3427
agrieve7b6479d82015-10-07 14:24:223428def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3429 """Checks if MDPI assets are placed in a correct directory."""
3430 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3431 ('/res/drawable/' in f.LocalPath() or
3432 '/res/drawable-ldrtl/' in f.LocalPath()))
3433 errors = []
3434 for f in input_api.AffectedFiles(include_deletes=False,
3435 file_filter=file_filter):
3436 errors.append(' %s' % f.LocalPath())
3437
3438 results = []
3439 if errors:
3440 results.append(output_api.PresubmitError(
3441 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3442 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3443 '/res/drawable-ldrtl/.\n'
3444 'Contact [email protected] if you have questions.', errors))
3445 return results
3446
3447
Nate Fischer535972b2017-09-16 01:06:183448def _CheckAndroidWebkitImports(input_api, output_api):
3449 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353450 android.webview.ValueCallback except in the WebView glue layer
3451 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183452 """
3453 valuecallback_import_pattern = input_api.re.compile(
3454 r'^import android\.webkit\.ValueCallback;$')
3455
3456 errors = []
3457
3458 sources = lambda affected_file: input_api.FilterSourceFile(
3459 affected_file,
3460 black_list=(_EXCLUDED_PATHS +
3461 _TEST_CODE_EXCLUDED_PATHS +
3462 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353463 (r'^android_webview[\\/]glue[\\/].*',
3464 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493465 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183466
3467 for f in input_api.AffectedSourceFiles(sources):
3468 for line_num, line in f.ChangedContents():
3469 if valuecallback_import_pattern.search(line):
3470 errors.append("%s:%d" % (f.LocalPath(), line_num))
3471
3472 results = []
3473
3474 if errors:
3475 results.append(output_api.PresubmitError(
3476 'android.webkit.ValueCallback usage is detected outside of the glue'
3477 ' layer. To stay compatible with the support library, android.webkit.*'
3478 ' classes should only be used inside the glue layer and'
3479 ' org.chromium.base.Callback should be used instead.',
3480 errors))
3481
3482 return results
3483
3484
Becky Zhou7c69b50992018-12-10 19:37:573485def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3486 """Checks Android XML styles """
3487 import sys
3488 original_sys_path = sys.path
3489 try:
3490 sys.path = sys.path + [input_api.os_path.join(
3491 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3492 import checkxmlstyle
3493 finally:
3494 # Restore sys.path to what it was before.
3495 sys.path = original_sys_path
3496
3497 if is_check_on_upload:
3498 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3499 else:
3500 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3501
3502
agrievef32bcc72016-04-04 14:57:403503class PydepsChecker(object):
3504 def __init__(self, input_api, pydeps_files):
3505 self._file_cache = {}
3506 self._input_api = input_api
3507 self._pydeps_files = pydeps_files
3508
3509 def _LoadFile(self, path):
3510 """Returns the list of paths within a .pydeps file relative to //."""
3511 if path not in self._file_cache:
3512 with open(path) as f:
3513 self._file_cache[path] = f.read()
3514 return self._file_cache[path]
3515
3516 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3517 """Returns an interable of paths within the .pydep, relativized to //."""
3518 os_path = self._input_api.os_path
3519 pydeps_dir = os_path.dirname(pydeps_path)
3520 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3521 if not l.startswith('*'))
3522 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3523
3524 def _CreateFilesToPydepsMap(self):
3525 """Returns a map of local_path -> list_of_pydeps."""
3526 ret = {}
3527 for pydep_local_path in self._pydeps_files:
3528 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3529 ret.setdefault(path, []).append(pydep_local_path)
3530 return ret
3531
3532 def ComputeAffectedPydeps(self):
3533 """Returns an iterable of .pydeps files that might need regenerating."""
3534 affected_pydeps = set()
3535 file_to_pydeps_map = None
3536 for f in self._input_api.AffectedFiles(include_deletes=True):
3537 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463538 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3539 # subrepositories. We can't figure out which files change, so re-check
3540 # all files.
3541 # Changes to print_python_deps.py affect all .pydeps.
3542 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403543 return self._pydeps_files
3544 elif local_path.endswith('.pydeps'):
3545 if local_path in self._pydeps_files:
3546 affected_pydeps.add(local_path)
3547 elif local_path.endswith('.py'):
3548 if file_to_pydeps_map is None:
3549 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3550 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3551 return affected_pydeps
3552
3553 def DetermineIfStale(self, pydeps_path):
3554 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413555 import difflib
John Budorick47ca3fe2018-02-10 00:53:103556 import os
3557
agrievef32bcc72016-04-04 14:57:403558 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3559 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103560 env = dict(os.environ)
3561 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403562 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103563 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413564 old_contents = old_pydeps_data[2:]
3565 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403566 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413567 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403568
3569
Tibor Goldschwendt360793f72019-06-25 18:23:493570def _ParseGclientArgs():
3571 args = {}
3572 with open('build/config/gclient_args.gni', 'r') as f:
3573 for line in f:
3574 line = line.strip()
3575 if not line or line.startswith('#'):
3576 continue
3577 attribute, value = line.split('=')
3578 args[attribute.strip()] = value.strip()
3579 return args
3580
3581
agrievef32bcc72016-04-04 14:57:403582def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3583 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403584 # This check is for Python dependency lists (.pydeps files), and involves
3585 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3586 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283587 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003588 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493589 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403590 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3591 results = []
3592 # First, check for new / deleted .pydeps.
3593 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033594 # Check whether we are running the presubmit check for a file in src.
3595 # f.LocalPath is relative to repo (src, or internal repo).
3596 # os_path.exists is relative to src repo.
3597 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3598 # to src and we can conclude that the pydeps is in src.
3599 if input_api.os_path.exists(f.LocalPath()):
3600 if f.LocalPath().endswith('.pydeps'):
3601 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3602 results.append(output_api.PresubmitError(
3603 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3604 'remove %s' % f.LocalPath()))
3605 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3606 results.append(output_api.PresubmitError(
3607 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3608 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403609
3610 if results:
3611 return results
3612
3613 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3614
3615 for pydep_path in checker.ComputeAffectedPydeps():
3616 try:
phajdan.jr0d9878552016-11-04 10:49:413617 result = checker.DetermineIfStale(pydep_path)
3618 if result:
3619 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403620 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413621 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3622 'To regenerate, run:\n\n %s' %
3623 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403624 except input_api.subprocess.CalledProcessError as error:
3625 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3626 long_text=error.output)]
3627
3628 return results
3629
3630
glidere61efad2015-02-18 17:39:433631def _CheckSingletonInHeaders(input_api, output_api):
3632 """Checks to make sure no header files have |Singleton<|."""
3633 def FileFilter(affected_file):
3634 # It's ok for base/memory/singleton.h to have |Singleton<|.
3635 black_list = (_EXCLUDED_PATHS +
3636 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043637 (r"^base[\\/]memory[\\/]singleton\.h$",
3638 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473639 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433640 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3641
sergeyu34d21222015-09-16 00:11:443642 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433643 files = []
3644 for f in input_api.AffectedSourceFiles(FileFilter):
3645 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3646 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3647 contents = input_api.ReadFile(f)
3648 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243649 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433650 pattern.search(line)):
3651 files.append(f)
3652 break
3653
3654 if files:
yolandyandaabc6d2016-04-18 18:29:393655 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443656 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433657 'Please move them to an appropriate source file so that the ' +
3658 'template gets instantiated in a single compilation unit.',
3659 files) ]
3660 return []
3661
3662
[email protected]fd20b902014-05-09 02:14:533663_DEPRECATED_CSS = [
3664 # Values
3665 ( "-webkit-box", "flex" ),
3666 ( "-webkit-inline-box", "inline-flex" ),
3667 ( "-webkit-flex", "flex" ),
3668 ( "-webkit-inline-flex", "inline-flex" ),
3669 ( "-webkit-min-content", "min-content" ),
3670 ( "-webkit-max-content", "max-content" ),
3671
3672 # Properties
3673 ( "-webkit-background-clip", "background-clip" ),
3674 ( "-webkit-background-origin", "background-origin" ),
3675 ( "-webkit-background-size", "background-size" ),
3676 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443677 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533678
3679 # Functions
3680 ( "-webkit-gradient", "gradient" ),
3681 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3682 ( "-webkit-linear-gradient", "linear-gradient" ),
3683 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3684 ( "-webkit-radial-gradient", "radial-gradient" ),
3685 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3686]
3687
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203688
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493689# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243690def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533691 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253692 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343693 documentation and iOS CSS for dom distiller
3694 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253695 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533696 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493697 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253698 black_list = (_EXCLUDED_PATHS +
3699 _TEST_CODE_EXCLUDED_PATHS +
3700 input_api.DEFAULT_BLACK_LIST +
3701 (r"^chrome/common/extensions/docs",
3702 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343703 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443704 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253705 r"^native_client_sdk"))
3706 file_filter = lambda f: input_api.FilterSourceFile(
3707 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533708 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3709 for line_num, line in fpath.ChangedContents():
3710 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023711 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533712 results.append(output_api.PresubmitError(
3713 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3714 (fpath.LocalPath(), line_num, deprecated_value, value)))
3715 return results
3716
mohan.reddyf21db962014-10-16 12:26:473717
rlanday6802cf632017-05-30 17:48:363718def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363719 bad_files = {}
3720 for f in input_api.AffectedFiles(include_deletes=False):
3721 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493722 not f.LocalPath().startswith('third_party/blink') and
3723 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363724 continue
3725
Daniel Bratell65b033262019-04-23 08:17:063726 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363727 continue
3728
Vaclav Brozekd5de76a2018-03-17 07:57:503729 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363730 if "#include" in line and "../" in line]
3731 if not relative_includes:
3732 continue
3733 bad_files[f.LocalPath()] = relative_includes
3734
3735 if not bad_files:
3736 return []
3737
3738 error_descriptions = []
3739 for file_path, bad_lines in bad_files.iteritems():
3740 error_description = file_path
3741 for line in bad_lines:
3742 error_description += '\n ' + line
3743 error_descriptions.append(error_description)
3744
3745 results = []
3746 results.append(output_api.PresubmitError(
3747 'You added one or more relative #include paths (including "../").\n'
3748 'These shouldn\'t be used because they can be used to include headers\n'
3749 'from code that\'s not correctly specified as a dependency in the\n'
3750 'relevant BUILD.gn file(s).',
3751 error_descriptions))
3752
3753 return results
3754
Takeshi Yoshinoe387aa32017-08-02 13:16:133755
Daniel Bratell65b033262019-04-23 08:17:063756def _CheckForCcIncludes(input_api, output_api):
3757 """Check that nobody tries to include a cc file. It's a relatively
3758 common error which results in duplicate symbols in object
3759 files. This may not always break the build until someone later gets
3760 very confusing linking errors."""
3761 results = []
3762 for f in input_api.AffectedFiles(include_deletes=False):
3763 # We let third_party code do whatever it wants
3764 if (f.LocalPath().startswith('third_party') and
3765 not f.LocalPath().startswith('third_party/blink') and
3766 not f.LocalPath().startswith('third_party\\blink')):
3767 continue
3768
3769 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3770 continue
3771
3772 for _, line in f.ChangedContents():
3773 if line.startswith('#include "'):
3774 included_file = line.split('"')[1]
3775 if _IsCPlusPlusFile(input_api, included_file):
3776 # The most common naming for external files with C++ code,
3777 # apart from standard headers, is to call them foo.inc, but
3778 # Chromium sometimes uses foo-inc.cc so allow that as well.
3779 if not included_file.endswith(('.h', '-inc.cc')):
3780 results.append(output_api.PresubmitError(
3781 'Only header files or .inc files should be included in other\n'
3782 'C++ files. Compiling the contents of a cc file more than once\n'
3783 'will cause duplicate information in the build which may later\n'
3784 'result in strange link_errors.\n' +
3785 f.LocalPath() + ':\n ' +
3786 line))
3787
3788 return results
3789
3790
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203791def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3792 if not isinstance(key, ast.Str):
3793 return 'Key at line %d must be a string literal' % key.lineno
3794 if not isinstance(value, ast.Dict):
3795 return 'Value at line %d must be a dict' % value.lineno
3796 if len(value.keys) != 1:
3797 return 'Dict at line %d must have single entry' % value.lineno
3798 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3799 return (
3800 'Entry at line %d must have a string literal \'filepath\' as key' %
3801 value.lineno)
3802 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133803
Takeshi Yoshinoe387aa32017-08-02 13:16:133804
Sergey Ulanov4af16052018-11-08 02:41:463805def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203806 if not isinstance(key, ast.Str):
3807 return 'Key at line %d must be a string literal' % key.lineno
3808 if not isinstance(value, ast.List):
3809 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463810 for element in value.elts:
3811 if not isinstance(element, ast.Str):
3812 return 'Watchlist elements on line %d is not a string' % key.lineno
3813 if not email_regex.match(element.s):
3814 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3815 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203816 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133817
Takeshi Yoshinoe387aa32017-08-02 13:16:133818
Sergey Ulanov4af16052018-11-08 02:41:463819def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203820 mismatch_template = (
3821 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3822 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133823
Sergey Ulanov4af16052018-11-08 02:41:463824 email_regex = input_api.re.compile(
3825 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3826
3827 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203828 i = 0
3829 last_key = ''
3830 while True:
3831 if i >= len(wd_dict.keys):
3832 if i >= len(w_dict.keys):
3833 return None
3834 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3835 elif i >= len(w_dict.keys):
3836 return (
3837 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133838
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203839 wd_key = wd_dict.keys[i]
3840 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133841
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203842 result = _CheckWatchlistDefinitionsEntrySyntax(
3843 wd_key, wd_dict.values[i], ast)
3844 if result is not None:
3845 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133846
Sergey Ulanov4af16052018-11-08 02:41:463847 result = _CheckWatchlistsEntrySyntax(
3848 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203849 if result is not None:
3850 return 'Bad entry in WATCHLISTS dict: %s' % result
3851
3852 if wd_key.s != w_key.s:
3853 return mismatch_template % (
3854 '%s at line %d' % (wd_key.s, wd_key.lineno),
3855 '%s at line %d' % (w_key.s, w_key.lineno))
3856
3857 if wd_key.s < last_key:
3858 return (
3859 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3860 (wd_key.lineno, w_key.lineno))
3861 last_key = wd_key.s
3862
3863 i = i + 1
3864
3865
Sergey Ulanov4af16052018-11-08 02:41:463866def _CheckWATCHLISTSSyntax(expression, input_api):
3867 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203868 if not isinstance(expression, ast.Expression):
3869 return 'WATCHLISTS file must contain a valid expression'
3870 dictionary = expression.body
3871 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3872 return 'WATCHLISTS file must have single dict with exactly two entries'
3873
3874 first_key = dictionary.keys[0]
3875 first_value = dictionary.values[0]
3876 second_key = dictionary.keys[1]
3877 second_value = dictionary.values[1]
3878
3879 if (not isinstance(first_key, ast.Str) or
3880 first_key.s != 'WATCHLIST_DEFINITIONS' or
3881 not isinstance(first_value, ast.Dict)):
3882 return (
3883 'The first entry of the dict in WATCHLISTS file must be '
3884 'WATCHLIST_DEFINITIONS dict')
3885
3886 if (not isinstance(second_key, ast.Str) or
3887 second_key.s != 'WATCHLISTS' or
3888 not isinstance(second_value, ast.Dict)):
3889 return (
3890 'The second entry of the dict in WATCHLISTS file must be '
3891 'WATCHLISTS dict')
3892
Sergey Ulanov4af16052018-11-08 02:41:463893 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133894
3895
3896def _CheckWATCHLISTS(input_api, output_api):
3897 for f in input_api.AffectedFiles(include_deletes=False):
3898 if f.LocalPath() == 'WATCHLISTS':
3899 contents = input_api.ReadFile(f, 'r')
3900
3901 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203902 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133903 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203904 # Get an AST tree for it and scan the tree for detailed style checking.
3905 expression = input_api.ast.parse(
3906 contents, filename='WATCHLISTS', mode='eval')
3907 except ValueError as e:
3908 return [output_api.PresubmitError(
3909 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3910 except SyntaxError as e:
3911 return [output_api.PresubmitError(
3912 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3913 except TypeError as e:
3914 return [output_api.PresubmitError(
3915 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133916
Sergey Ulanov4af16052018-11-08 02:41:463917 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203918 if result is not None:
3919 return [output_api.PresubmitError(result)]
3920 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133921
3922 return []
3923
3924
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193925def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3926 """Checks that newly added header files have corresponding GN changes.
3927 Note that this is only a heuristic. To be precise, run script:
3928 build/check_gn_headers.py.
3929 """
3930
3931 def headers(f):
3932 return input_api.FilterSourceFile(
3933 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3934
3935 new_headers = []
3936 for f in input_api.AffectedSourceFiles(headers):
3937 if f.Action() != 'A':
3938 continue
3939 new_headers.append(f.LocalPath())
3940
3941 def gn_files(f):
3942 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3943
3944 all_gn_changed_contents = ''
3945 for f in input_api.AffectedSourceFiles(gn_files):
3946 for _, line in f.ChangedContents():
3947 all_gn_changed_contents += line
3948
3949 problems = []
3950 for header in new_headers:
3951 basename = input_api.os_path.basename(header)
3952 if basename not in all_gn_changed_contents:
3953 problems.append(header)
3954
3955 if problems:
3956 return [output_api.PresubmitPromptWarning(
3957 'Missing GN changes for new header files', items=sorted(problems),
3958 long_text='Please double check whether newly added header files need '
3959 'corresponding changes in gn or gni files.\nThis checking is only a '
3960 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3961 'Read https://crbug.com/661774 for more info.')]
3962 return []
3963
3964
Michael Giuffridad3bc8672018-10-25 22:48:023965def _CheckCorrectProductNameInMessages(input_api, output_api):
3966 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3967
3968 This assumes we won't intentionally reference one product from the other
3969 product.
3970 """
3971 all_problems = []
3972 test_cases = [{
3973 "filename_postfix": "google_chrome_strings.grd",
3974 "correct_name": "Chrome",
3975 "incorrect_name": "Chromium",
3976 }, {
3977 "filename_postfix": "chromium_strings.grd",
3978 "correct_name": "Chromium",
3979 "incorrect_name": "Chrome",
3980 }]
3981
3982 for test_case in test_cases:
3983 problems = []
3984 filename_filter = lambda x: x.LocalPath().endswith(
3985 test_case["filename_postfix"])
3986
3987 # Check each new line. Can yield false positives in multiline comments, but
3988 # easier than trying to parse the XML because messages can have nested
3989 # children, and associating message elements with affected lines is hard.
3990 for f in input_api.AffectedSourceFiles(filename_filter):
3991 for line_num, line in f.ChangedContents():
3992 if "<message" in line or "<!--" in line or "-->" in line:
3993 continue
3994 if test_case["incorrect_name"] in line:
3995 problems.append(
3996 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3997
3998 if problems:
3999 message = (
4000 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
4001 % (test_case["correct_name"], test_case["correct_name"],
4002 test_case["incorrect_name"]))
4003 all_problems.append(
4004 output_api.PresubmitPromptWarning(message, items=problems))
4005
4006 return all_problems
4007
4008
Dirk Pranke3c18a382019-03-15 01:07:514009def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4010 # TODO(crbug.com/941824): We need to make sure the entries in
4011 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4012 # so that users of //buildtools in other projects get the same tooling
4013 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4014 # support to gclient, we can eliminate the duplication and delete
4015 # this presubmit check.
4016
4017 # Update this regexp if new revisions are added to the files.
4018 rev_regexp = input_api.re.compile(
Xiaohui Chen3fdc6742020-02-29 02:13:264019 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:514020
4021 # If a user is changing one revision, they need to change the same
4022 # line in both files. This means that any given change should contain
4023 # exactly the same list of changed lines that match the regexps. The
4024 # replace(' ', '') call allows us to ignore whitespace changes to the
4025 # lines. The 'long_text' parameter to the error will contain the
4026 # list of changed lines in both files, which should make it easy enough
4027 # to spot the error without going overboard in this implementation.
4028 revs_changes = {
4029 'DEPS': {},
4030 'buildtools/DEPS': {},
4031 }
4032 long_text = ''
4033
4034 for f in input_api.AffectedFiles(
4035 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4036 for line_num, line in f.ChangedContents():
4037 if rev_regexp.search(line):
4038 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4039 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4040
4041 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4042 return [output_api.PresubmitError(
4043 'Change buildtools revisions in sync in both //DEPS and '
4044 '//buildtools/DEPS.', long_text=long_text + '\n')]
4045 else:
4046 return []
4047
4048
Daniel Bratell93eb6c62019-04-29 20:13:364049def _CheckForTooLargeFiles(input_api, output_api):
4050 """Avoid large files, especially binary files, in the repository since
4051 git doesn't scale well for those. They will be in everyone's repo
4052 clones forever, forever making Chromium slower to clone and work
4053 with."""
4054
4055 # Uploading files to cloud storage is not trivial so we don't want
4056 # to set the limit too low, but the upper limit for "normal" large
4057 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4058 # anything over 20 MB is exceptional.
4059 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4060
4061 too_large_files = []
4062 for f in input_api.AffectedFiles():
4063 # Check both added and modified files (but not deleted files).
4064 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384065 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364066 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4067 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4068
4069 if too_large_files:
4070 message = (
4071 'Do not commit large files to git since git scales badly for those.\n' +
4072 'Instead put the large files in cloud storage and use DEPS to\n' +
4073 'fetch them.\n' + '\n'.join(too_large_files)
4074 )
4075 return [output_api.PresubmitError(
4076 'Too large files found in commit', long_text=message + '\n')]
4077 else:
4078 return []
4079
Max Morozb47503b2019-08-08 21:03:274080
4081def _CheckFuzzTargets(input_api, output_api):
4082 """Checks specific for fuzz target sources."""
4083 EXPORTED_SYMBOLS = [
4084 'LLVMFuzzerInitialize',
4085 'LLVMFuzzerCustomMutator',
4086 'LLVMFuzzerCustomCrossOver',
4087 'LLVMFuzzerMutate',
4088 ]
4089
4090 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4091
4092 def FilterFile(affected_file):
4093 """Ignore libFuzzer source code."""
4094 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4095 black_list = r"^third_party[\\/]libFuzzer"
4096
4097 return input_api.FilterSourceFile(
4098 affected_file,
4099 white_list=[white_list],
4100 black_list=[black_list])
4101
4102 files_with_missing_header = []
4103 for f in input_api.AffectedSourceFiles(FilterFile):
4104 contents = input_api.ReadFile(f, 'r')
4105 if REQUIRED_HEADER in contents:
4106 continue
4107
4108 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4109 files_with_missing_header.append(f.LocalPath())
4110
4111 if not files_with_missing_header:
4112 return []
4113
4114 long_text = (
4115 'If you define any of the libFuzzer optional functions (%s), it is '
4116 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4117 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4118 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4119 'to access command line arguments passed to the fuzzer. Instead, prefer '
4120 'static initialization and shared resources as documented in '
4121 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4122 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4123 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4124 )
4125
4126 return [output_api.PresubmitPromptWarning(
4127 message="Missing '%s' in:" % REQUIRED_HEADER,
4128 items=files_with_missing_header,
4129 long_text=long_text)]
4130
4131
Mohamed Heikald048240a2019-11-12 16:57:374132def _CheckNewImagesWarning(input_api, output_api):
4133 """
4134 Warns authors who add images into the repo to make sure their images are
4135 optimized before committing.
4136 """
4137 images_added = False
4138 image_paths = []
4139 errors = []
4140 filter_lambda = lambda x: input_api.FilterSourceFile(
4141 x,
4142 black_list=(('(?i).*test', r'.*\/junit\/')
4143 + input_api.DEFAULT_BLACK_LIST),
4144 white_list=[r'.*\/(drawable|mipmap)' ]
4145 )
4146 for f in input_api.AffectedFiles(
4147 include_deletes=False, file_filter=filter_lambda):
4148 local_path = f.LocalPath().lower()
4149 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4150 images_added = True
4151 image_paths.append(f)
4152 if images_added:
4153 errors.append(output_api.PresubmitPromptWarning(
4154 'It looks like you are trying to commit some images. If these are '
4155 'non-test-only images, please make sure to read and apply the tips in '
4156 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4157 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4158 'FYI only and will not block your CL on the CQ.', image_paths))
4159 return errors
4160
4161
dgnaa68d5e2015-06-10 10:08:224162def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574163 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224164 results = []
dgnaa68d5e2015-06-10 10:08:224165 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174166 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224167 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294168 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064169 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4170 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424171 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184172 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574173 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374174 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154175 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574176 return results
4177
4178def _AndroidSpecificOnCommitChecks(input_api, output_api):
4179 """Groups commit checks that target android code."""
4180 results = []
4181 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224182 return results
4183
4184
[email protected]22c9bd72011-03-27 16:47:394185def _CommonChecks(input_api, output_api):
4186 """Checks common to both upload and commit."""
4187 results = []
4188 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384189 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544190 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084191
4192 author = input_api.change.author_email
4193 if author and author not in _KNOWN_ROBOTS:
4194 results.extend(
4195 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4196
[email protected]55459852011-08-10 15:17:194197 results.extend(
[email protected]760deea2013-12-10 19:33:494198 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234199 results.extend(
4200 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544201 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184202 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344203 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524204 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224205 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444206 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594207 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314208 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064209 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124210 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184211 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224212 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304213 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494214 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034215 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494216 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444217 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294218 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274219 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074220 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544221 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444222 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394223 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554224 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044225 results.extend(
4226 input_api.canned_checks.CheckChangeHasNoTabs(
4227 input_api,
4228 output_api,
4229 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404230 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164231 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084232 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244233 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474234 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044235 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054236 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144237 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234238 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434239 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404240 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154241 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174242 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264243 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504244 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364245 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064246 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134247 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434248 results.extend(input_api.RunTests(
4249 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144250 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024251 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514252 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364253 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004254 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244255
Vaclav Brozekcdc7defb2018-03-20 09:54:354256 for f in input_api.AffectedFiles():
4257 path, name = input_api.os_path.split(f.LocalPath())
4258 if name == 'PRESUBMIT.py':
4259 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004260 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4261 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074262 # The PRESUBMIT.py file (and the directory containing it) might
4263 # have been affected by being moved or removed, so only try to
4264 # run the tests if they still exist.
4265 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4266 input_api, output_api, full_path,
4267 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394268 return results
[email protected]1f7b4172010-01-28 01:17:344269
[email protected]b337cb5b2011-01-23 21:24:054270
[email protected]b8079ae4a2012-12-05 19:56:494271def _CheckPatchFiles(input_api, output_api):
4272 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4273 if f.LocalPath().endswith(('.orig', '.rej'))]
4274 if problems:
4275 return [output_api.PresubmitError(
4276 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034277 else:
4278 return []
[email protected]b8079ae4a2012-12-05 19:56:494279
4280
Kent Tamura5a8755d2017-06-29 23:37:074281def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214282 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4283 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4284 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074285 include_re = input_api.re.compile(
4286 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4287 extension_re = input_api.re.compile(r'\.[a-z]+$')
4288 errors = []
4289 for f in input_api.AffectedFiles():
4290 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4291 continue
4292 found_line_number = None
4293 found_macro = None
4294 for line_num, line in f.ChangedContents():
4295 match = macro_re.search(line)
4296 if match:
4297 found_line_number = line_num
4298 found_macro = match.group(2)
4299 break
4300 if not found_line_number:
4301 continue
4302
4303 found_include = False
4304 for line in f.NewContents():
4305 if include_re.search(line):
4306 found_include = True
4307 break
4308 if found_include:
4309 continue
4310
4311 if not f.LocalPath().endswith('.h'):
4312 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4313 try:
4314 content = input_api.ReadFile(primary_header_path, 'r')
4315 if include_re.search(content):
4316 continue
4317 except IOError:
4318 pass
4319 errors.append('%s:%d %s macro is used without including build/'
4320 'build_config.h.'
4321 % (f.LocalPath(), found_line_number, found_macro))
4322 if errors:
4323 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4324 return []
4325
4326
[email protected]b00342e7f2013-03-26 16:21:544327def _DidYouMeanOSMacro(bad_macro):
4328 try:
4329 return {'A': 'OS_ANDROID',
4330 'B': 'OS_BSD',
4331 'C': 'OS_CHROMEOS',
4332 'F': 'OS_FREEBSD',
4333 'L': 'OS_LINUX',
4334 'M': 'OS_MACOSX',
4335 'N': 'OS_NACL',
4336 'O': 'OS_OPENBSD',
4337 'P': 'OS_POSIX',
4338 'S': 'OS_SOLARIS',
4339 'W': 'OS_WIN'}[bad_macro[3].upper()]
4340 except KeyError:
4341 return ''
4342
4343
4344def _CheckForInvalidOSMacrosInFile(input_api, f):
4345 """Check for sensible looking, totally invalid OS macros."""
4346 preprocessor_statement = input_api.re.compile(r'^\s*#')
4347 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4348 results = []
4349 for lnum, line in f.ChangedContents():
4350 if preprocessor_statement.search(line):
4351 for match in os_macro.finditer(line):
4352 if not match.group(1) in _VALID_OS_MACROS:
4353 good = _DidYouMeanOSMacro(match.group(1))
4354 did_you_mean = ' (did you mean %s?)' % good if good else ''
4355 results.append(' %s:%d %s%s' % (f.LocalPath(),
4356 lnum,
4357 match.group(1),
4358 did_you_mean))
4359 return results
4360
4361
4362def _CheckForInvalidOSMacros(input_api, output_api):
4363 """Check all affected files for invalid OS macros."""
4364 bad_macros = []
tzik3f295992018-12-04 20:32:234365 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474366 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544367 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4368
4369 if not bad_macros:
4370 return []
4371
4372 return [output_api.PresubmitError(
4373 'Possibly invalid OS macro[s] found. Please fix your code\n'
4374 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4375
lliabraa35bab3932014-10-01 12:16:444376
4377def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4378 """Check all affected files for invalid "if defined" macros."""
4379 ALWAYS_DEFINED_MACROS = (
4380 "TARGET_CPU_PPC",
4381 "TARGET_CPU_PPC64",
4382 "TARGET_CPU_68K",
4383 "TARGET_CPU_X86",
4384 "TARGET_CPU_ARM",
4385 "TARGET_CPU_MIPS",
4386 "TARGET_CPU_SPARC",
4387 "TARGET_CPU_ALPHA",
4388 "TARGET_IPHONE_SIMULATOR",
4389 "TARGET_OS_EMBEDDED",
4390 "TARGET_OS_IPHONE",
4391 "TARGET_OS_MAC",
4392 "TARGET_OS_UNIX",
4393 "TARGET_OS_WIN32",
4394 )
4395 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4396 results = []
4397 for lnum, line in f.ChangedContents():
4398 for match in ifdef_macro.finditer(line):
4399 if match.group(1) in ALWAYS_DEFINED_MACROS:
4400 always_defined = ' %s is always defined. ' % match.group(1)
4401 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4402 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4403 lnum,
4404 always_defined,
4405 did_you_mean))
4406 return results
4407
4408
4409def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4410 """Check all affected files for invalid "if defined" macros."""
4411 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054412 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444413 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054414 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214415 continue
lliabraa35bab3932014-10-01 12:16:444416 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4417 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4418
4419 if not bad_macros:
4420 return []
4421
4422 return [output_api.PresubmitError(
4423 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4424 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4425 bad_macros)]
4426
4427
mlamouria82272622014-09-16 18:45:044428def _CheckForIPCRules(input_api, output_api):
4429 """Check for same IPC rules described in
4430 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4431 """
4432 base_pattern = r'IPC_ENUM_TRAITS\('
4433 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4434 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4435
4436 problems = []
4437 for f in input_api.AffectedSourceFiles(None):
4438 local_path = f.LocalPath()
4439 if not local_path.endswith('.h'):
4440 continue
4441 for line_number, line in f.ChangedContents():
4442 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4443 problems.append(
4444 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4445
4446 if problems:
4447 return [output_api.PresubmitPromptWarning(
4448 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4449 else:
4450 return []
4451
[email protected]b00342e7f2013-03-26 16:21:544452
Stephen Martinis97a394142018-06-07 23:06:054453def _CheckForLongPathnames(input_api, output_api):
4454 """Check to make sure no files being submitted have long paths.
4455 This causes issues on Windows.
4456 """
4457 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194458 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054459 local_path = f.LocalPath()
4460 # Windows has a path limit of 260 characters. Limit path length to 200 so
4461 # that we have some extra for the prefix on dev machines and the bots.
4462 if len(local_path) > 200:
4463 problems.append(local_path)
4464
4465 if problems:
4466 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4467 else:
4468 return []
4469
4470
Daniel Bratell8ba52722018-03-02 16:06:144471def _CheckForIncludeGuards(input_api, output_api):
4472 """Check that header files have proper guards against multiple inclusion.
4473 If a file should not have such guards (and it probably should) then it
4474 should include the string "no-include-guard-because-multiply-included".
4475 """
Daniel Bratell6a75baef62018-06-04 10:04:454476 def is_chromium_header_file(f):
4477 # We only check header files under the control of the Chromium
4478 # project. That is, those outside third_party apart from
4479 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324480 # We also exclude *_message_generator.h headers as they use
4481 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454482 file_with_path = input_api.os_path.normpath(f.LocalPath())
4483 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324484 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454485 (not file_with_path.startswith('third_party') or
4486 file_with_path.startswith(
4487 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144488
4489 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344490 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144491
4492 errors = []
4493
Daniel Bratell6a75baef62018-06-04 10:04:454494 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144495 guard_name = None
4496 guard_line_number = None
4497 seen_guard_end = False
4498
4499 file_with_path = input_api.os_path.normpath(f.LocalPath())
4500 base_file_name = input_api.os_path.splitext(
4501 input_api.os_path.basename(file_with_path))[0]
4502 upper_base_file_name = base_file_name.upper()
4503
4504 expected_guard = replace_special_with_underscore(
4505 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144506
4507 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574508 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4509 # are too many (1000+) files with slight deviations from the
4510 # coding style. The most important part is that the include guard
4511 # is there, and that it's unique, not the name so this check is
4512 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144513 #
4514 # As code becomes more uniform, this could be made stricter.
4515
4516 guard_name_pattern_list = [
4517 # Anything with the right suffix (maybe with an extra _).
4518 r'\w+_H__?',
4519
Daniel Bratell39b5b062018-05-16 18:09:574520 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144521 r'\w+_h',
4522
4523 # Anything including the uppercase name of the file.
4524 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4525 upper_base_file_name)) + r'\w*',
4526 ]
4527 guard_name_pattern = '|'.join(guard_name_pattern_list)
4528 guard_pattern = input_api.re.compile(
4529 r'#ifndef\s+(' + guard_name_pattern + ')')
4530
4531 for line_number, line in enumerate(f.NewContents()):
4532 if 'no-include-guard-because-multiply-included' in line:
4533 guard_name = 'DUMMY' # To not trigger check outside the loop.
4534 break
4535
4536 if guard_name is None:
4537 match = guard_pattern.match(line)
4538 if match:
4539 guard_name = match.group(1)
4540 guard_line_number = line_number
4541
Daniel Bratell39b5b062018-05-16 18:09:574542 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454543 # don't match the chromium style guide, but new files should
4544 # get it right.
4545 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574546 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144547 errors.append(output_api.PresubmitPromptWarning(
4548 'Header using the wrong include guard name %s' % guard_name,
4549 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574550 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144551 else:
4552 # The line after #ifndef should have a #define of the same name.
4553 if line_number == guard_line_number + 1:
4554 expected_line = '#define %s' % guard_name
4555 if line != expected_line:
4556 errors.append(output_api.PresubmitPromptWarning(
4557 'Missing "%s" for include guard' % expected_line,
4558 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4559 'Expected: %r\nGot: %r' % (expected_line, line)))
4560
4561 if not seen_guard_end and line == '#endif // %s' % guard_name:
4562 seen_guard_end = True
4563 elif seen_guard_end:
4564 if line.strip() != '':
4565 errors.append(output_api.PresubmitPromptWarning(
4566 'Include guard %s not covering the whole file' % (
4567 guard_name), [f.LocalPath()]))
4568 break # Nothing else to check and enough to warn once.
4569
4570 if guard_name is None:
4571 errors.append(output_api.PresubmitPromptWarning(
4572 'Missing include guard %s' % expected_guard,
4573 [f.LocalPath()],
4574 'Missing include guard in %s\n'
4575 'Recommended name: %s\n'
4576 'This check can be disabled by having the string\n'
4577 'no-include-guard-because-multiply-included in the header.' %
4578 (f.LocalPath(), expected_guard)))
4579
4580 return errors
4581
4582
mostynbb639aca52015-01-07 20:31:234583def _CheckForWindowsLineEndings(input_api, output_api):
4584 """Check source code and known ascii text files for Windows style line
4585 endings.
4586 """
earthdok1b5e0ee2015-03-10 15:19:104587 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234588
4589 file_inclusion_pattern = (
4590 known_text_files,
4591 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4592 )
4593
mostynbb639aca52015-01-07 20:31:234594 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534595 source_file_filter = lambda f: input_api.FilterSourceFile(
4596 f, white_list=file_inclusion_pattern, black_list=None)
4597 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504598 include_file = False
4599 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234600 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504601 include_file = True
4602 if include_file:
4603 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234604
4605 if problems:
4606 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4607 'these files to contain Windows style line endings?\n' +
4608 '\n'.join(problems))]
4609
4610 return []
4611
4612
Vaclav Brozekd5de76a2018-03-17 07:57:504613def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134614 """Checks that all source files use SYSLOG properly."""
4615 syslog_files = []
4616 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564617 for line_number, line in f.ChangedContents():
4618 if 'SYSLOG' in line:
4619 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4620
pastarmovj89f7ee12016-09-20 14:58:134621 if syslog_files:
4622 return [output_api.PresubmitPromptWarning(
4623 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4624 ' calls.\nFiles to check:\n', items=syslog_files)]
4625 return []
4626
4627
[email protected]1f7b4172010-01-28 01:17:344628def CheckChangeOnUpload(input_api, output_api):
4629 results = []
4630 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474631 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284632 results.extend(
jam93a6ee792017-02-08 23:59:224633 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194634 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224635 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134636 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164637 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534638 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194639 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274640 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544641 return results
[email protected]ca8d1982009-02-19 16:33:124642
4643
[email protected]1bfb8322014-04-23 01:02:414644def GetTryServerMasterForBot(bot):
4645 """Returns the Try Server master for the given bot.
4646
[email protected]0bb112362014-07-26 04:38:324647 It tries to guess the master from the bot name, but may still fail
4648 and return None. There is no longer a default master.
4649 """
4650 # Potentially ambiguous bot names are listed explicitly.
4651 master_map = {
tandriie5587792016-07-14 00:34:504652 'chromium_presubmit': 'master.tryserver.chromium.linux',
4653 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414654 }
[email protected]0bb112362014-07-26 04:38:324655 master = master_map.get(bot)
4656 if not master:
wnwen4fbaab82016-05-25 12:54:364657 if 'android' in bot:
tandriie5587792016-07-14 00:34:504658 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364659 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504660 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324661 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504662 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324663 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504664 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324665 return master
[email protected]1bfb8322014-04-23 01:02:414666
4667
[email protected]ca8d1982009-02-19 16:33:124668def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544669 results = []
[email protected]1f7b4172010-01-28 01:17:344670 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574671 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544672 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274673 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344674 input_api,
4675 output_api,
[email protected]2fdd1f362013-01-16 03:56:034676 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274677
jam93a6ee792017-02-08 23:59:224678 results.extend(
4679 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544680 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4681 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384682 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4683 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414684 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4685 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544686 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144687
4688
4689def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144690 import os
4691 import sys
4692 from io import StringIO
4693
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144694 new_or_added_paths = set(f.LocalPath()
4695 for f in input_api.AffectedFiles()
4696 if (f.Action() == 'A' or f.Action() == 'M'))
4697 removed_paths = set(f.LocalPath()
4698 for f in input_api.AffectedFiles(include_deletes=True)
4699 if f.Action() == 'D')
4700
4701 affected_grds = [f for f in input_api.AffectedFiles()
4702 if (f.LocalPath().endswith('.grd') or
4703 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164704 if not affected_grds:
4705 return []
4706
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144707 affected_png_paths = [f.AbsoluteLocalPath()
4708 for f in input_api.AffectedFiles()
4709 if (f.LocalPath().endswith('.png'))]
4710
4711 # Check for screenshots. Developers can upload screenshots using
4712 # tools/translation/upload_screenshots.py which finds and uploads
4713 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4714 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4715 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4716 #
4717 # The logic here is as follows:
4718 #
4719 # - If the CL has a .png file under the screenshots directory for a grd
4720 # file, warn the developer. Actual images should never be checked into the
4721 # Chrome repo.
4722 #
4723 # - If the CL contains modified or new messages in grd files and doesn't
4724 # contain the corresponding .sha1 files, warn the developer to add images
4725 # and upload them via tools/translation/upload_screenshots.py.
4726 #
4727 # - If the CL contains modified or new messages in grd files and the
4728 # corresponding .sha1 files, everything looks good.
4729 #
4730 # - If the CL contains removed messages in grd files but the corresponding
4731 # .sha1 files aren't removed, warn the developer to remove them.
4732 unnecessary_screenshots = []
4733 missing_sha1 = []
4734 unnecessary_sha1_files = []
4735
4736
4737 def _CheckScreenshotAdded(screenshots_dir, message_id):
4738 sha1_path = input_api.os_path.join(
4739 screenshots_dir, message_id + '.png.sha1')
4740 if sha1_path not in new_or_added_paths:
4741 missing_sha1.append(sha1_path)
4742
4743
4744 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4745 sha1_path = input_api.os_path.join(
4746 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034747 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144748 unnecessary_sha1_files.append(sha1_path)
4749
meacer8c0d3832019-12-26 21:46:164750 try:
4751 old_sys_path = sys.path
4752 sys.path = sys.path + [input_api.os_path.join(
4753 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4754 from helper import grd_helper
4755 finally:
4756 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144757
4758 for f in affected_grds:
4759 file_path = f.LocalPath()
4760 old_id_to_msg_map = {}
4761 new_id_to_msg_map = {}
Mustafa Emre Acerd697ac92020-02-06 19:03:384762 # Note that this code doesn't check if the file has been deleted. This is
4763 # OK because it only uses the old and new file contents and doesn't load
4764 # the file via its path.
4765 # It's also possible that a file's content refers to a renamed or deleted
4766 # file via a <part> tag, such as <part file="now-deleted-file.grdp">. This
4767 # is OK as well, because grd_helper ignores <part> tags when loading .grd or
4768 # .grdp files.
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144769 if file_path.endswith('.grdp'):
4770 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584771 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394772 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144773 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584774 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394775 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144776 else:
meacerff8a9b62019-12-10 19:43:584777 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144778 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584779 old_id_to_msg_map = grd_helper.GetGrdMessages(
4780 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144781 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584782 new_id_to_msg_map = grd_helper.GetGrdMessages(
4783 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144784
4785 # Compute added, removed and modified message IDs.
4786 old_ids = set(old_id_to_msg_map)
4787 new_ids = set(new_id_to_msg_map)
4788 added_ids = new_ids - old_ids
4789 removed_ids = old_ids - new_ids
4790 modified_ids = set([])
4791 for key in old_ids.intersection(new_ids):
4792 if (old_id_to_msg_map[key].FormatXml()
4793 != new_id_to_msg_map[key].FormatXml()):
4794 modified_ids.add(key)
4795
4796 grd_name, ext = input_api.os_path.splitext(
4797 input_api.os_path.basename(file_path))
4798 screenshots_dir = input_api.os_path.join(
4799 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4800
4801 # Check the screenshot directory for .png files. Warn if there is any.
4802 for png_path in affected_png_paths:
4803 if png_path.startswith(screenshots_dir):
4804 unnecessary_screenshots.append(png_path)
4805
4806 for added_id in added_ids:
4807 _CheckScreenshotAdded(screenshots_dir, added_id)
4808
4809 for modified_id in modified_ids:
4810 _CheckScreenshotAdded(screenshots_dir, modified_id)
4811
4812 for removed_id in removed_ids:
4813 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4814
4815 results = []
4816 if unnecessary_screenshots:
4817 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394818 'Do not include actual screenshots in the changelist. Run '
4819 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144820 sorted(unnecessary_screenshots)))
4821
4822 if missing_sha1:
4823 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394824 'You are adding or modifying UI strings.\n'
4825 'To ensure the best translations, take screenshots of the relevant UI '
4826 '(https://g.co/chrome/translation) and add these files to your '
4827 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144828
4829 if unnecessary_sha1_files:
4830 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394831 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144832 sorted(unnecessary_sha1_files)))
4833
4834 return results