blob: 5fc0c3bf2bd47bf67b6ebf4ea4496994500b54f0 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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/',
286 '^chrome/chrome_watcher/',
287 '^chrome/common/',
288 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51289 '^chrome/renderer/',
290 '^chrome/services/',
291 '^chrome/test/',
292 '^chrome/tools/',
293 '^chrome/utility/',
danakj7a2b7082019-05-21 21:13:51294 '^chromecast/media/',
295 '^chromecast/metrics/',
296 '^chromecast/net/',
297 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51298 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51299 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51300 '^chromeos/services/',
danakj7a2b7082019-05-21 21:13:51301 '^components/arc/',
302 '^components/assist_ranker/',
303 '^components/autofill/',
304 '^components/autofill_assistant/',
danakj7a2b7082019-05-21 21:13:51305 '^components/browser_watcher/',
306 '^components/browsing_data/',
307 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51308 '^components/chromeos_camera/',
309 '^components/component_updater/',
310 '^components/content_settings/',
danakj7a2b7082019-05-21 21:13:51311 '^components/cronet/',
312 '^components/data_reduction_proxy/',
313 '^components/discardable_memory/',
danakj7a2b7082019-05-21 21:13:51314 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36315 '^components/dom_distiller/',
danakj7a2b7082019-05-21 21:13:51316 '^components/download/',
317 '^components/drive/',
318 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51319 '^components/feature_engagement/',
320 '^components/feedback/',
321 '^components/flags_ui/',
322 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51323 '^components/guest_view/',
324 '^components/heap_profiling/',
325 '^components/history/',
326 '^components/image_fetcher/',
327 '^components/invalidation/',
328 '^components/keyed_service/',
329 '^components/login/',
330 '^components/metrics/',
331 '^components/metrics_services_manager/',
332 '^components/nacl/',
333 '^components/navigation_interception/',
334 '^components/net_log/',
335 '^components/network_time/',
336 '^components/ntp_snippets/',
337 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51338 '^components/offline_pages/',
339 '^components/omnibox/',
340 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51341 '^components/password_manager/',
342 '^components/payments/',
343 '^components/plugins/',
344 '^components/policy/',
danakj7a2b7082019-05-21 21:13:51345 '^components/proxy_config/',
346 '^components/quirks/',
danakj7a2b7082019-05-21 21:13:51347 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51348 '^components/rlz/',
349 '^components/safe_browsing/',
350 '^components/search_engines/',
351 '^components/search_provider_logos/',
352 '^components/security_interstitials/',
353 '^components/security_state/',
354 '^components/services/',
355 '^components/sessions/',
356 '^components/signin/',
357 '^components/ssl_errors/',
358 '^components/storage_monitor/',
359 '^components/subresource_filter/',
360 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51361 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51362 '^components/sync_preferences/',
363 '^components/sync_sessions/',
364 '^components/test/',
365 '^components/tracing/',
366 '^components/translate/',
367 '^components/ukm/',
368 '^components/update_client/',
369 '^components/upload_list/',
370 '^components/variations/',
371 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51372 '^components/webcrypto/',
373 '^components/webdata/',
374 '^components/webdata_services/',
danakj7a2b7082019-05-21 21:13:51375 '^device/bluetooth/',
danakj7a2b7082019-05-21 21:13:51376 '^extensions/',
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/',
408 '^remoting/codec/',
409 '^remoting/host/',
410 '^remoting/internal/',
411 '^remoting/ios/',
412 '^remoting/protocol/',
413 '^remoting/signaling/',
414 '^remoting/test/',
danakj7a2b7082019-05-21 21:13:51415 '^services/',
danakj7a2b7082019-05-21 21:13:51416 '^third_party/blink/',
danakj7a2b7082019-05-21 21:13:51417 '^tools/clang/base_bind_rewriters/', # Intentional.
418 '^tools/gdb/gdb_chrome.py', # Intentional.
danakj7a2b7082019-05-21 21:13:51419))
[email protected]127f18ec2012-06-16 05:05:59420
Daniel Bratell609102be2019-03-27 20:53:21421# Format: Sequence of tuples containing:
422# * String pattern or, if starting with a slash, a regular expression.
423# * Sequence of strings to show when the pattern matches.
424# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
425# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59426_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20427 (
Dave Tapuska98199b612019-07-10 13:30:44428 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53429 (
430 'New code should not use NULL. Use nullptr instead.',
431 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20432 False,
thomasandersone7caaa9b2017-03-29 19:22:53433 (),
434 ),
Peter Kasting94a56c42019-10-25 21:54:04435 (
436 r'/\busing namespace ',
437 (
438 'Using directives ("using namespace x") are banned by the Google Style',
439 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
440 'Explicitly qualify symbols or use using declarations ("using x::foo").',
441 ),
442 True,
443 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
444 ),
Antonio Gomes07300d02019-03-13 20:59:57445 # Make sure that gtest's FRIEND_TEST() macro is not used; the
446 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
447 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53448 (
[email protected]23e6cbc2012-06-16 18:51:20449 'FRIEND_TEST(',
450 (
[email protected]e3c945502012-06-26 20:01:49451 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20452 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
453 ),
454 False,
[email protected]7345da02012-11-27 14:31:49455 (),
[email protected]23e6cbc2012-06-16 18:51:20456 ),
457 (
Dave Tapuska98199b612019-07-10 13:30:44458 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53459 (
460 'Chrome clients wishing to select events on X windows should use',
461 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
462 'you are selecting events from the GPU process, or if you are using',
463 'an XDisplay other than gfx::GetXDisplay().',
464 ),
465 True,
466 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40467 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04468 r"^ui[\\/]gl[\\/].*\.cc$",
469 r"^media[\\/]gpu[\\/].*\.cc$",
470 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53471 ),
472 ),
473 (
Dave Tapuska98199b612019-07-10 13:30:44474 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20475 (
thomasanderson11aa41d2017-06-08 22:22:38476 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20477 ),
478 True,
479 (
Egor Paskoce145c42018-09-28 19:31:04480 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
481 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
482 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20483 ),
484 ),
485 (
tomhudsone2c14d552016-05-26 17:07:46486 'setMatrixClip',
487 (
488 'Overriding setMatrixClip() is prohibited; ',
489 'the base function is deprecated. ',
490 ),
491 True,
492 (),
493 ),
494 (
[email protected]52657f62013-05-20 05:30:31495 'SkRefPtr',
496 (
497 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22498 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31499 ),
500 True,
501 (),
502 ),
503 (
504 'SkAutoRef',
505 (
506 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22507 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31508 ),
509 True,
510 (),
511 ),
512 (
513 'SkAutoTUnref',
514 (
515 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22516 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31517 ),
518 True,
519 (),
520 ),
521 (
522 'SkAutoUnref',
523 (
524 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
525 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22526 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31527 ),
528 True,
529 (),
530 ),
[email protected]d89eec82013-12-03 14:10:59531 (
532 r'/HANDLE_EINTR\(.*close',
533 (
534 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
535 'descriptor will be closed, and it is incorrect to retry the close.',
536 'Either call close directly and ignore its return value, or wrap close',
537 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
538 ),
539 True,
540 (),
541 ),
542 (
543 r'/IGNORE_EINTR\((?!.*close)',
544 (
545 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
546 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
547 ),
548 True,
549 (
550 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04551 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
552 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59553 ),
554 ),
[email protected]ec5b3f02014-04-04 18:43:43555 (
556 r'/v8::Extension\(',
557 (
558 'Do not introduce new v8::Extensions into the code base, use',
559 'gin::Wrappable instead. See http://crbug.com/334679',
560 ),
561 True,
[email protected]f55c90ee62014-04-12 00:50:03562 (
Egor Paskoce145c42018-09-28 19:31:04563 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03564 ),
[email protected]ec5b3f02014-04-04 18:43:43565 ),
skyostilf9469f72015-04-20 10:38:52566 (
jame2d1a952016-04-02 00:27:10567 '#pragma comment(lib,',
568 (
569 'Specify libraries to link with in build files and not in the source.',
570 ),
571 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41572 (
tzik3f295992018-12-04 20:32:23573 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04574 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41575 ),
jame2d1a952016-04-02 00:27:10576 ),
fdorayc4ac18d2017-05-01 21:39:59577 (
Gabriel Charette7cc6c432018-04-25 20:52:02578 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59579 (
580 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
581 ),
582 False,
583 (),
584 ),
585 (
Gabriel Charette7cc6c432018-04-25 20:52:02586 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59587 (
588 'Consider using THREAD_CHECKER macros instead of the class directly.',
589 ),
590 False,
591 (),
592 ),
dbeamb6f4fde2017-06-15 04:03:06593 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06594 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
595 (
596 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
597 'deprecated (http://crbug.com/634507). Please avoid converting away',
598 'from the Time types in Chromium code, especially if any math is',
599 'being done on time values. For interfacing with platform/library',
600 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
601 'type converter methods instead. For faking TimeXXX values (for unit',
602 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
603 'other use cases, please contact base/time/OWNERS.',
604 ),
605 False,
606 (),
607 ),
608 (
dbeamb6f4fde2017-06-15 04:03:06609 'CallJavascriptFunctionUnsafe',
610 (
611 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
612 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
613 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
614 ),
615 False,
616 (
Egor Paskoce145c42018-09-28 19:31:04617 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
618 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
619 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06620 ),
621 ),
dskiba1474c2bfd62017-07-20 02:19:24622 (
623 'leveldb::DB::Open',
624 (
625 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
626 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
627 "Chrome's tracing, making their memory usage visible.",
628 ),
629 True,
630 (
631 r'^third_party/leveldatabase/.*\.(cc|h)$',
632 ),
Gabriel Charette0592c3a2017-07-26 12:02:04633 ),
634 (
Chris Mumfordc38afb62017-10-09 17:55:08635 'leveldb::NewMemEnv',
636 (
637 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58638 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
639 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08640 ),
641 True,
642 (
643 r'^third_party/leveldatabase/.*\.(cc|h)$',
644 ),
645 ),
646 (
Gabriel Charetted9839bc2017-07-29 14:17:47647 'RunLoop::QuitCurrent',
648 (
Robert Liao64b7ab22017-08-04 23:03:43649 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
650 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47651 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41652 False,
Gabriel Charetted9839bc2017-07-29 14:17:47653 (),
Gabriel Charettea44975052017-08-21 23:14:04654 ),
655 (
656 'base::ScopedMockTimeMessageLoopTaskRunner',
657 (
Gabriel Charette87cc1af2018-04-25 20:52:51658 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11659 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51660 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
661 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
662 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04663 ),
Gabriel Charette87cc1af2018-04-25 20:52:51664 False,
Gabriel Charettea44975052017-08-21 23:14:04665 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57666 ),
667 (
Dave Tapuska98199b612019-07-10 13:30:44668 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57669 (
670 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02671 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57672 ),
673 True,
674 (),
Francois Doray43670e32017-09-27 12:40:38675 ),
676 (
Peter Kasting991618a62019-06-17 22:00:09677 r'/\bstd::stoi\b',
678 (
679 'std::stoi uses exceptions to communicate results. ',
680 'Use base::StringToInt() instead.',
681 ),
682 True,
683 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
684 ),
685 (
686 r'/\bstd::stol\b',
687 (
688 'std::stol uses exceptions to communicate results. ',
689 'Use base::StringToInt() instead.',
690 ),
691 True,
692 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
693 ),
694 (
695 r'/\bstd::stoul\b',
696 (
697 'std::stoul uses exceptions to communicate results. ',
698 'Use base::StringToUint() instead.',
699 ),
700 True,
701 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
702 ),
703 (
704 r'/\bstd::stoll\b',
705 (
706 'std::stoll uses exceptions to communicate results. ',
707 'Use base::StringToInt64() instead.',
708 ),
709 True,
710 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
711 ),
712 (
713 r'/\bstd::stoull\b',
714 (
715 'std::stoull uses exceptions to communicate results. ',
716 'Use base::StringToUint64() instead.',
717 ),
718 True,
719 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
720 ),
721 (
722 r'/\bstd::stof\b',
723 (
724 'std::stof uses exceptions to communicate results. ',
725 'For locale-independent values, e.g. reading numbers from disk',
726 'profiles, use base::StringToDouble().',
727 'For user-visible values, parse using ICU.',
728 ),
729 True,
730 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
731 ),
732 (
733 r'/\bstd::stod\b',
734 (
735 'std::stod uses exceptions to communicate results. ',
736 'For locale-independent values, e.g. reading numbers from disk',
737 'profiles, use base::StringToDouble().',
738 'For user-visible values, parse using ICU.',
739 ),
740 True,
741 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
742 ),
743 (
744 r'/\bstd::stold\b',
745 (
746 'std::stold uses exceptions to communicate results. ',
747 'For locale-independent values, e.g. reading numbers from disk',
748 'profiles, use base::StringToDouble().',
749 'For user-visible values, parse using ICU.',
750 ),
751 True,
752 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
753 ),
754 (
Daniel Bratell69334cc2019-03-26 11:07:45755 r'/\bstd::to_string\b',
756 (
757 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09758 'For locale-independent strings, e.g. writing numbers to disk',
759 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45760 'For user-visible strings, use base::FormatNumber() and',
761 'the related functions in base/i18n/number_formatting.h.',
762 ),
Peter Kasting991618a62019-06-17 22:00:09763 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21764 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45765 ),
766 (
767 r'/\bstd::shared_ptr\b',
768 (
769 'std::shared_ptr should not be used. Use scoped_refptr instead.',
770 ),
771 True,
Andreas Haas63f58792019-11-07 10:56:44772 [_THIRD_PARTY_EXCEPT_BLINK,
773 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
774 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21775 ),
776 (
Peter Kasting991618a62019-06-17 22:00:09777 r'/\bstd::weak_ptr\b',
778 (
779 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
780 ),
781 True,
782 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
783 ),
784 (
Daniel Bratell609102be2019-03-27 20:53:21785 r'/\blong long\b',
786 (
787 'long long is banned. Use stdint.h if you need a 64 bit number.',
788 ),
789 False, # Only a warning since it is already used.
790 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
791 ),
792 (
793 r'/\bstd::bind\b',
794 (
795 'std::bind is banned because of lifetime risks.',
796 'Use base::BindOnce or base::BindRepeating instead.',
797 ),
798 True,
799 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
800 ),
801 (
802 r'/\b#include <chrono>\b',
803 (
804 '<chrono> overlaps with Time APIs in base. Keep using',
805 'base classes.',
806 ),
807 True,
808 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
809 ),
810 (
811 r'/\b#include <exception>\b',
812 (
813 'Exceptions are banned and disabled in Chromium.',
814 ),
815 True,
816 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
817 ),
818 (
819 r'/\bstd::function\b',
820 (
821 'std::function is banned. Instead use base::Callback which directly',
822 'supports Chromium\'s weak pointers, ref counting and more.',
823 ),
Peter Kasting991618a62019-06-17 22:00:09824 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21825 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
826 ),
827 (
828 r'/\b#include <random>\b',
829 (
830 'Do not use any random number engines from <random>. Instead',
831 'use base::RandomBitGenerator.',
832 ),
833 True,
834 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
835 ),
836 (
837 r'/\bstd::ratio\b',
838 (
839 'std::ratio is banned by the Google Style Guide.',
840 ),
841 True,
842 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45843 ),
844 (
Francois Doray43670e32017-09-27 12:40:38845 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
846 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
847 (
848 'Use the new API in base/threading/thread_restrictions.h.',
849 ),
Gabriel Charette04b138f2018-08-06 00:03:22850 False,
Francois Doray43670e32017-09-27 12:40:38851 (),
852 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38853 (
danakj7a2b7082019-05-21 21:13:51854 r'/\bbase::Bind\(',
855 (
856 'Please use base::Bind{Once,Repeating} instead',
857 'of base::Bind. (crbug.com/714018)',
858 ),
859 False,
Erik Staaba737d7602019-11-25 18:41:07860 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51861 ),
862 (
863 r'/\bbase::Callback[<:]',
864 (
865 'Please use base::{Once,Repeating}Callback instead',
866 'of base::Callback. (crbug.com/714018)',
867 ),
868 False,
Erik Staaba737d7602019-11-25 18:41:07869 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51870 ),
871 (
872 r'/\bbase::Closure\b',
873 (
874 'Please use base::{Once,Repeating}Closure instead',
875 'of base::Closure. (crbug.com/714018)',
876 ),
877 False,
Erik Staaba737d7602019-11-25 18:41:07878 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51879 ),
880 (
Michael Giuffrida7f93d6922019-04-19 14:39:58881 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19882 (
883 'RunMessageLoop is deprecated, use RunLoop instead.',
884 ),
885 False,
886 (),
887 ),
888 (
Dave Tapuska98199b612019-07-10 13:30:44889 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19890 (
891 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
892 ),
893 False,
894 (),
895 ),
896 (
Dave Tapuska98199b612019-07-10 13:30:44897 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19898 (
899 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
900 "if you're convinced you need this.",
901 ),
902 False,
903 (),
904 ),
905 (
Dave Tapuska98199b612019-07-10 13:30:44906 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19907 (
908 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04909 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19910 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
911 'async events instead of flushing threads.',
912 ),
913 False,
914 (),
915 ),
916 (
917 r'MessageLoopRunner',
918 (
919 'MessageLoopRunner is deprecated, use RunLoop instead.',
920 ),
921 False,
922 (),
923 ),
924 (
Dave Tapuska98199b612019-07-10 13:30:44925 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19926 (
927 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
928 "gab@ if you found a use case where this is the only solution.",
929 ),
930 False,
931 (),
932 ),
933 (
Victor Costane48a2e82019-03-15 22:02:34934 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16935 (
Victor Costane48a2e82019-03-15 22:02:34936 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16937 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
938 ),
939 True,
940 (
941 r'^sql/initialization\.(cc|h)$',
942 r'^third_party/sqlite/.*\.(c|cc|h)$',
943 ),
944 ),
Matt Menke7f520a82018-03-28 21:38:37945 (
946 'net::URLFetcher',
947 (
948 'net::URLFetcher should no longer be used in content embedders. ',
949 'Instead, use network::SimpleURLLoader instead, which supports ',
950 'an out-of-process network stack. ',
951 'net::URLFetcher may still be used in binaries that do not embed',
952 'content.',
953 ),
Matt Menke59716d02018-04-05 12:45:53954 False,
Matt Menke7f520a82018-03-28 21:38:37955 (
Egor Paskoce145c42018-09-28 19:31:04956 r'^ios[\\/].*\.(cc|h)$',
957 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37958 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04959 r'^net[\\/].*\.(cc|h)$',
960 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43961 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37962 ),
963 ),
jdoerried7d10ab2018-04-27 10:46:13964 (
Dave Tapuska98199b612019-07-10 13:30:44965 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47966 (
967 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
968 'base::RandomShuffle instead.'
969 ),
970 True,
971 (),
972 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24973 (
974 'ios/web/public/test/http_server',
975 (
976 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
977 ),
978 False,
979 (),
980 ),
Robert Liao764c9492019-01-24 18:46:28981 (
982 'GetAddressOf',
983 (
984 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:46985 'implicated in a few leaks. Use operator& instead. See ',
986 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:28987 ),
988 True,
989 (),
990 ),
Antonio Gomes07300d02019-03-13 20:59:57991 (
992 'DEFINE_TYPE_CASTS',
993 (
994 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
995 '//third_party/blink/renderer/platform/casting.h.'
996 ),
997 True,
998 (
999 r'^third_party/blink/renderer/.*\.(cc|h)$',
1000 ),
1001 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381002 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:451003 r'/\bIsHTML.+Element\(\b',
1004 (
1005 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1006 ' helpers IsA<HTMLXXXXElement> from ',
1007 '//third_party/blink/renderer/platform/casting.h.'
1008 ),
1009 False,
1010 (
1011 r'^third_party/blink/renderer/.*\.(cc|h)$',
1012 ),
1013 ),
1014 (
1015 r'/\bToHTML.+Element(|OrNull)\(\b',
1016 (
1017 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1018 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1019 'and DynamicTo<HTMLXXXXElement> from ',
1020 '//third_party/blink/renderer/platform/casting.h.'
1021 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1022 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1023 ),
1024 False,
1025 (
1026 r'^third_party/blink/renderer/.*\.(cc|h)$',
1027 ),
1028 ),
1029 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371030 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381031 (
1032 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1033 ),
1034 True,
1035 (),
1036 ),
Ben Lewisa9514602019-04-29 17:53:051037 (
1038 'SHFileOperation',
1039 (
1040 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1041 'complex functions to achieve the same goals. Use IFileOperation for ',
1042 'any esoteric actions instead.'
1043 ),
1044 True,
1045 (),
1046 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181047 (
Cliff Smolinsky81951642019-04-30 21:39:511048 'StringFromGUID2',
1049 (
1050 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1051 'Use base::win::String16FromGUID instead.'
1052 ),
1053 True,
1054 (
1055 r'/base/win/win_util_unittest.cc'
1056 ),
1057 ),
1058 (
1059 'StringFromCLSID',
1060 (
1061 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1062 'Use base::win::String16FromGUID instead.'
1063 ),
1064 True,
1065 (
1066 r'/base/win/win_util_unittest.cc'
1067 ),
1068 ),
1069 (
Avi Drissman7382afa02019-04-29 23:27:131070 'kCFAllocatorNull',
1071 (
1072 'The use of kCFAllocatorNull with the NoCopy creation of ',
1073 'CoreFoundation types is prohibited.',
1074 ),
1075 True,
1076 (),
1077 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291078 (
1079 'mojo::ConvertTo',
1080 (
1081 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1082 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1083 'StringTraits if you would like to convert between custom types and',
1084 'the wire format of mojom types.'
1085 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221086 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291087 (
Wezf89dec092019-09-11 19:38:331088 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1089 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291090 r'^third_party/blink/.*\.(cc|h)$',
1091 r'^content/renderer/.*\.(cc|h)$',
1092 ),
1093 ),
Robert Liao1d78df52019-11-11 20:02:011094 (
Oksana Zhuravlovac8222d22019-12-19 19:21:161095 'GetInterfaceProvider',
1096 (
1097 'InterfaceProvider is deprecated.',
1098 'Please use ExecutionContext::GetBrowserInterfaceBroker and overrides',
1099 'or Platform::GetBrowserInterfaceBroker.'
1100 ),
1101 False,
1102 (),
1103 ),
1104 (
Robert Liao1d78df52019-11-11 20:02:011105 'CComPtr',
1106 (
1107 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1108 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1109 'details.'
1110 ),
1111 False,
1112 (),
1113 ),
[email protected]127f18ec2012-06-16 05:05:591114)
1115
Mario Sanchez Prada2472cab2019-09-18 10:58:311116# Format: Sequence of tuples containing:
1117# * String pattern or, if starting with a slash, a regular expression.
1118# * Sequence of strings to show when the pattern matches.
1119_DEPRECATED_MOJO_TYPES = (
1120 (
1121 r'/\bmojo::AssociatedBinding\b',
1122 (
1123 'mojo::AssociatedBinding<Interface> is deprecated.',
1124 'Use mojo::AssociatedReceiver<Interface> instead.',
1125 ),
1126 ),
1127 (
1128 r'/\bmojo::AssociatedBindingSet\b',
1129 (
1130 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1131 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1132 ),
1133 ),
1134 (
1135 r'/\bmojo::AssociatedInterfacePtr\b',
1136 (
1137 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1138 'Use mojo::AssociatedRemote<Interface> instead.',
1139 ),
1140 ),
1141 (
1142 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1143 (
1144 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1145 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1146 ),
1147 ),
1148 (
1149 r'/\bmojo::AssociatedInterfaceRequest\b',
1150 (
1151 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1152 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1153 ),
1154 ),
1155 (
1156 r'/\bmojo::Binding\b',
1157 (
1158 'mojo::Binding<Interface> is deprecated.',
1159 'Use mojo::Receiver<Interface> instead.',
1160 ),
1161 ),
1162 (
1163 r'/\bmojo::BindingSet\b',
1164 (
1165 'mojo::BindingSet<Interface> is deprecated.',
1166 'Use mojo::ReceiverSet<Interface> instead.',
1167 ),
1168 ),
1169 (
1170 r'/\bmojo::InterfacePtr\b',
1171 (
1172 'mojo::InterfacePtr<Interface> is deprecated.',
1173 'Use mojo::Remote<Interface> instead.',
1174 ),
1175 ),
1176 (
1177 r'/\bmojo::InterfacePtrInfo\b',
1178 (
1179 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1180 'Use mojo::PendingRemote<Interface> instead.',
1181 ),
1182 ),
1183 (
1184 r'/\bmojo::InterfaceRequest\b',
1185 (
1186 'mojo::InterfaceRequest<Interface> is deprecated.',
1187 'Use mojo::PendingReceiver<Interface> instead.',
1188 ),
1189 ),
1190 (
1191 r'/\bmojo::MakeRequest\b',
1192 (
1193 'mojo::MakeRequest is deprecated.',
1194 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1195 ),
1196 ),
1197 (
1198 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1199 (
1200 'mojo::MakeRequest is deprecated.',
1201 'Use mojo::AssociatedRemote::'
1202 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1203 ),
1204 ),
1205 (
1206 r'/\bmojo::MakeStrongBinding\b',
1207 (
1208 'mojo::MakeStrongBinding is deprecated.',
1209 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1210 'mojo::MakeSelfOwnedReceiver() instead.',
1211 ),
1212 ),
1213 (
1214 r'/\bmojo::MakeStrongAssociatedBinding\b',
1215 (
1216 'mojo::MakeStrongAssociatedBinding is deprecated.',
1217 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1218 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1219 ),
1220 ),
1221 (
1222 r'/\bmojo::StrongAssociatedBindingSet\b',
1223 (
1224 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1225 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1226 ),
1227 ),
1228 (
1229 r'/\bmojo::StrongBindingSet\b',
1230 (
1231 'mojo::StrongBindingSet<Interface> is deprecated.',
1232 'Use mojo::UniqueReceiverSet<Interface> instead.',
1233 ),
1234 ),
1235)
wnwenbdc444e2016-05-25 13:44:151236
mlamouria82272622014-09-16 18:45:041237_IPC_ENUM_TRAITS_DEPRECATED = (
1238 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501239 'See http://www.chromium.org/Home/chromium-security/education/'
1240 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041241
Stephen Martinis97a394142018-06-07 23:06:051242_LONG_PATH_ERROR = (
1243 'Some files included in this CL have file names that are too long (> 200'
1244 ' characters). If committed, these files will cause issues on Windows. See'
1245 ' https://crbug.com/612667 for more details.'
1246)
1247
Shenghua Zhangbfaa38b82017-11-16 21:58:021248_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041249 r".*[\\/]BuildHooksAndroidImpl\.java",
1250 r".*[\\/]LicenseContentProvider\.java",
1251 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281252 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021253]
[email protected]127f18ec2012-06-16 05:05:591254
Mohamed Heikald048240a2019-11-12 16:57:371255# List of image extensions that are used as resources in chromium.
1256_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1257
Sean Kau46e29bc2017-08-28 16:31:161258# These paths contain test data and other known invalid JSON files.
1259_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041260 r'test[\\/]data[\\/]',
1261 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1262 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041263 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431264 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161265]
1266
1267
[email protected]b00342e7f2013-03-26 16:21:541268_VALID_OS_MACROS = (
1269 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081270 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541271 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121272 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541273 'OS_BSD',
1274 'OS_CAT', # For testing.
1275 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041276 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541277 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371278 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_IOS',
1280 'OS_LINUX',
1281 'OS_MACOSX',
1282 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211283 'OS_NACL_NONSFI',
1284 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121285 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541286 'OS_OPENBSD',
1287 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371288 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541289 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541290 'OS_WIN',
1291)
1292
1293
agrievef32bcc72016-04-04 14:57:401294_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391295 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361296 'base/android/jni_generator/jni_generator.pydeps',
1297 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221298 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361299 'build/android/gyp/aar.pydeps',
1300 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271301 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361302 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381303 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361304 'build/android/gyp/bytecode_processor.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111305 'build/android/gyp/compile_java.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361306 'build/android/gyp/compile_resources.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361307 'build/android/gyp/copy_ex.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/create_apk_operations_script.pydeps',
Andrew Grieve8d083ea2019-12-13 06:49:111309 'build/android/gyp/create_app_bundle_apks.pydeps',
1310 'build/android/gyp/create_app_bundle.pydeps',
1311 'build/android/gyp/create_bundle_wrapper_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361312 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221313 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361314 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591315 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361316 'build/android/gyp/dex.pydeps',
1317 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361318 'build/android/gyp/filter_zip.pydeps',
1319 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361320 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361321 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581322 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361323 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261324 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361325 'build/android/gyp/jinja_template.pydeps',
1326 'build/android/gyp/lint.pydeps',
1327 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361328 'build/android/gyp/merge_manifest.pydeps',
1329 'build/android/gyp/prepare_resources.pydeps',
1330 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241331 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361332 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461333 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561334 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361335 'build/android/incremental_install/generate_android_manifest.pydeps',
1336 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221337 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401338 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041339 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361340 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411341 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051342 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191343 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431344 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021345 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401346]
1347
wnwenbdc444e2016-05-25 13:44:151348
agrievef32bcc72016-04-04 14:57:401349_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421350 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131351 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421352 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1353 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131354 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
Caleb Raitto28864fc2020-01-07 00:18:191355 ('third_party/blink/renderer/bindings/scripts/'
1356 'generate_high_entropy_list.pydeps'),
John Budorickbc3571aa2019-04-25 02:20:061357 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221358 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401359]
1360
wnwenbdc444e2016-05-25 13:44:151361
agrievef32bcc72016-04-04 14:57:401362_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1363
1364
Eric Boren6fd2b932018-01-25 15:05:081365# Bypass the AUTHORS check for these accounts.
1366_KNOWN_ROBOTS = set(
Sergiy Byelozyorov47158a52018-06-13 22:38:591367 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451368 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591369 ) | set('%[email protected]' % s
smutde797052019-12-04 02:03:521370 for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder',
1371 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041372 ) | set('%[email protected]' % s
Eric Boren66150e52020-01-08 11:20:271373 for s in ('chromium-autoroll', 'chromium-release-autoroll')
Eric Boren835d71f2018-09-07 21:09:041374 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301375 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081376
1377
Daniel Bratell65b033262019-04-23 08:17:061378def _IsCPlusPlusFile(input_api, file_path):
1379 """Returns True if this file contains C++-like code (and not Python,
1380 Go, Java, MarkDown, ...)"""
1381
1382 ext = input_api.os_path.splitext(file_path)[1]
1383 # This list is compatible with CppChecker.IsCppFile but we should
1384 # consider adding ".c" to it. If we do that we can use this function
1385 # at more places in the code.
1386 return ext in (
1387 '.h',
1388 '.cc',
1389 '.cpp',
1390 '.m',
1391 '.mm',
1392 )
1393
1394def _IsCPlusPlusHeaderFile(input_api, file_path):
1395 return input_api.os_path.splitext(file_path)[1] == ".h"
1396
1397
1398def _IsJavaFile(input_api, file_path):
1399 return input_api.os_path.splitext(file_path)[1] == ".java"
1400
1401
1402def _IsProtoFile(input_api, file_path):
1403 return input_api.os_path.splitext(file_path)[1] == ".proto"
1404
[email protected]55459852011-08-10 15:17:191405def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1406 """Attempts to prevent use of functions intended only for testing in
1407 non-testing code. For now this is just a best-effort implementation
1408 that ignores header files and may have some false positives. A
1409 better implementation would probably need a proper C++ parser.
1410 """
1411 # We only scan .cc files and the like, as the declaration of
1412 # for-testing functions in header files are hard to distinguish from
1413 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491414 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191415
jochenc0d4808c2015-07-27 09:25:421416 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191417 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091418 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191419 exclusion_pattern = input_api.re.compile(
1420 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1421 base_function_pattern, base_function_pattern))
1422
1423 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441424 black_list = (_EXCLUDED_PATHS +
1425 _TEST_CODE_EXCLUDED_PATHS +
1426 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191427 return input_api.FilterSourceFile(
1428 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491429 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191430 black_list=black_list)
1431
1432 problems = []
1433 for f in input_api.AffectedSourceFiles(FilterFile):
1434 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241435 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031436 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461437 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031438 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191439 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031440 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191441
1442 if problems:
[email protected]f7051d52013-04-02 18:31:421443 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031444 else:
1445 return []
[email protected]55459852011-08-10 15:17:191446
1447
Vaclav Brozek7dbc28c2018-03-27 08:35:231448def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1449 """This is a simplified version of
1450 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1451 """
1452 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1453 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1454 name_pattern = r'ForTest(s|ing)?'
1455 # Describes an occurrence of "ForTest*" inside a // comment.
1456 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1457 # Catch calls.
1458 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1459 # Ignore definitions. (Comments are ignored separately.)
1460 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1461
1462 problems = []
1463 sources = lambda x: input_api.FilterSourceFile(
1464 x,
1465 black_list=(('(?i).*test', r'.*\/junit\/')
1466 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491467 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231468 )
1469 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1470 local_path = f.LocalPath()
1471 is_inside_javadoc = False
1472 for line_number, line in f.ChangedContents():
1473 if is_inside_javadoc and javadoc_end_re.search(line):
1474 is_inside_javadoc = False
1475 if not is_inside_javadoc and javadoc_start_re.search(line):
1476 is_inside_javadoc = True
1477 if is_inside_javadoc:
1478 continue
1479 if (inclusion_re.search(line) and
1480 not comment_re.search(line) and
1481 not exclusion_re.search(line)):
1482 problems.append(
1483 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1484
1485 if problems:
1486 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1487 else:
1488 return []
1489
1490
[email protected]10689ca2011-09-02 02:31:541491def _CheckNoIOStreamInHeaders(input_api, output_api):
1492 """Checks to make sure no .h files include <iostream>."""
1493 files = []
1494 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1495 input_api.re.MULTILINE)
1496 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1497 if not f.LocalPath().endswith('.h'):
1498 continue
1499 contents = input_api.ReadFile(f)
1500 if pattern.search(contents):
1501 files.append(f)
1502
1503 if len(files):
yolandyandaabc6d2016-04-18 18:29:391504 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061505 'Do not #include <iostream> in header files, since it inserts static '
1506 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541507 '#include <ostream>. See http://crbug.com/94794',
1508 files) ]
1509 return []
1510
Danil Chapovalov3518f362018-08-11 16:13:431511def _CheckNoStrCatRedefines(input_api, output_api):
1512 """Checks no windows headers with StrCat redefined are included directly."""
1513 files = []
1514 pattern_deny = input_api.re.compile(
1515 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1516 input_api.re.MULTILINE)
1517 pattern_allow = input_api.re.compile(
1518 r'^#include\s"base/win/windows_defines.inc"',
1519 input_api.re.MULTILINE)
1520 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1521 contents = input_api.ReadFile(f)
1522 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1523 files.append(f.LocalPath())
1524
1525 if len(files):
1526 return [output_api.PresubmitError(
1527 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1528 'directly since they pollute code with StrCat macro. Instead, '
1529 'include matching header from base/win. See http://crbug.com/856536',
1530 files) ]
1531 return []
1532
[email protected]10689ca2011-09-02 02:31:541533
[email protected]72df4e782012-06-21 16:28:181534def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521535 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181536 problems = []
1537 for f in input_api.AffectedFiles():
1538 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1539 continue
1540
1541 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041542 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181543 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1544
1545 if not problems:
1546 return []
1547 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1548 '\n'.join(problems))]
1549
Dominic Battre033531052018-09-24 15:45:341550def _CheckNoDISABLETypoInTests(input_api, output_api):
1551 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1552
1553 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1554 instead of DISABLED_. To filter false positives, reports are only generated
1555 if a corresponding MAYBE_ line exists.
1556 """
1557 problems = []
1558
1559 # The following two patterns are looked for in tandem - is a test labeled
1560 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1561 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1562 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1563
1564 # This is for the case that a test is disabled on all platforms.
1565 full_disable_pattern = input_api.re.compile(
1566 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1567 input_api.re.MULTILINE)
1568
Katie Df13948e2018-09-25 07:33:441569 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341570 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1571 continue
1572
1573 # Search for MABYE_, DISABLE_ pairs.
1574 disable_lines = {} # Maps of test name to line number.
1575 maybe_lines = {}
1576 for line_num, line in f.ChangedContents():
1577 disable_match = disable_pattern.search(line)
1578 if disable_match:
1579 disable_lines[disable_match.group(1)] = line_num
1580 maybe_match = maybe_pattern.search(line)
1581 if maybe_match:
1582 maybe_lines[maybe_match.group(1)] = line_num
1583
1584 # Search for DISABLE_ occurrences within a TEST() macro.
1585 disable_tests = set(disable_lines.keys())
1586 maybe_tests = set(maybe_lines.keys())
1587 for test in disable_tests.intersection(maybe_tests):
1588 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1589
1590 contents = input_api.ReadFile(f)
1591 full_disable_match = full_disable_pattern.search(contents)
1592 if full_disable_match:
1593 problems.append(' %s' % f.LocalPath())
1594
1595 if not problems:
1596 return []
1597 return [
1598 output_api.PresubmitPromptWarning(
1599 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1600 '\n'.join(problems))
1601 ]
1602
[email protected]72df4e782012-06-21 16:28:181603
danakj61c1aa22015-10-26 19:55:521604def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571605 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521606 errors = []
1607 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1608 input_api.re.MULTILINE)
1609 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1610 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1611 continue
1612 for lnum, line in f.ChangedContents():
1613 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171614 errors.append(output_api.PresubmitError(
1615 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571616 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171617 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521618 return errors
1619
1620
Makoto Shimazu3ad422cd2019-05-08 02:35:141621def _FindHistogramNameInChunk(histogram_name, chunk):
1622 """Tries to find a histogram name or prefix in a line.
1623
1624 Returns the existence of the histogram name, or None if it needs more chunk
1625 to determine."""
mcasasb7440c282015-02-04 14:52:191626 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1627 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141628 if '<affected-histogram' in chunk:
1629 # If the tag is not completed, needs more chunk to get the name.
1630 if not '>' in chunk:
1631 return None
1632 if not 'name="' in chunk:
1633 return False
1634 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1635 # expect the only attribute is the name.
1636 histogram_prefix = chunk.split('"')[1]
1637 return histogram_prefix in histogram_name
1638 # Typically the whole histogram name should in the line.
1639 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191640
1641
1642def _CheckUmaHistogramChanges(input_api, output_api):
1643 """Check that UMA histogram names in touched lines can still be found in other
1644 lines of the patch or in histograms.xml. Note that this check would not catch
1645 the reverse: changes in histograms.xml not matched in the code itself."""
1646 touched_histograms = []
1647 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471648 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1649 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1650 name_pattern = r'"(.*?)"'
1651 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1652 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1653 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1654 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1655 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171656 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191657 for f in input_api.AffectedFiles():
1658 # If histograms.xml itself is modified, keep the modified lines for later.
1659 if f.LocalPath().endswith(('histograms.xml')):
1660 histograms_xml_modifications = f.ChangedContents()
1661 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471662 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1663 single_line_re = single_line_c_re
1664 split_line_prefix_re = split_line_c_prefix_re
1665 elif f.LocalPath().endswith(('java')):
1666 single_line_re = single_line_java_re
1667 split_line_prefix_re = split_line_java_prefix_re
1668 else:
mcasasb7440c282015-02-04 14:52:191669 continue
1670 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171671 if last_line_matched_prefix:
1672 suffix_found = split_line_suffix_re.search(line)
1673 if suffix_found :
1674 touched_histograms.append([suffix_found.group(1), f, line_num])
1675 last_line_matched_prefix = False
1676 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061677 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191678 if found:
1679 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171680 continue
1681 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191682
1683 # Search for the touched histogram names in the local modifications to
1684 # histograms.xml, and, if not found, on the base histograms.xml file.
1685 unmatched_histograms = []
1686 for histogram_info in touched_histograms:
1687 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141688 chunk = ''
mcasasb7440c282015-02-04 14:52:191689 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141690 chunk += line
1691 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1692 if histogram_name_found is None:
1693 continue
1694 chunk = ''
mcasasb7440c282015-02-04 14:52:191695 if histogram_name_found:
1696 break
1697 if not histogram_name_found:
1698 unmatched_histograms.append(histogram_info)
1699
eromanb90c82e7e32015-04-01 15:13:491700 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191701 problems = []
1702 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491703 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191704 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451705 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191706 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141707 chunk = ''
mcasasb7440c282015-02-04 14:52:191708 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141709 chunk += line
1710 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1711 chunk)
1712 if histogram_name_found is None:
1713 continue
1714 chunk = ''
mcasasb7440c282015-02-04 14:52:191715 if histogram_name_found:
1716 break
1717 if not histogram_name_found:
1718 problems.append(' [%s:%d] %s' %
1719 (f.LocalPath(), line_num, histogram_name))
1720
1721 if not problems:
1722 return []
1723 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1724 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491725 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191726
wnwenbdc444e2016-05-25 13:44:151727
yolandyandaabc6d2016-04-18 18:29:391728def _CheckFlakyTestUsage(input_api, output_api):
1729 """Check that FlakyTest annotation is our own instead of the android one"""
1730 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1731 files = []
1732 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1733 if f.LocalPath().endswith('Test.java'):
1734 if pattern.search(input_api.ReadFile(f)):
1735 files.append(f)
1736 if len(files):
1737 return [output_api.PresubmitError(
1738 'Use org.chromium.base.test.util.FlakyTest instead of '
1739 'android.test.FlakyTest',
1740 files)]
1741 return []
mcasasb7440c282015-02-04 14:52:191742
wnwenbdc444e2016-05-25 13:44:151743
[email protected]8ea5d4b2011-09-13 21:49:221744def _CheckNoNewWStrings(input_api, output_api):
1745 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271746 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221747 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201748 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571749 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341750 '/win/' in f.LocalPath() or
1751 'chrome_elf' in f.LocalPath() or
1752 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201753 continue
[email protected]8ea5d4b2011-09-13 21:49:221754
[email protected]a11dbe9b2012-08-07 01:32:581755 allowWString = False
[email protected]b5c24292011-11-28 14:38:201756 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581757 if 'presubmit: allow wstring' in line:
1758 allowWString = True
1759 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271760 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581761 allowWString = False
1762 else:
1763 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221764
[email protected]55463aa62011-10-12 00:48:271765 if not problems:
1766 return []
1767 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581768 ' If you are calling a cross-platform API that accepts a wstring, '
1769 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271770 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221771
1772
[email protected]2a8ac9c2011-10-19 17:20:441773def _CheckNoDEPSGIT(input_api, output_api):
1774 """Make sure .DEPS.git is never modified manually."""
1775 if any(f.LocalPath().endswith('.DEPS.git') for f in
1776 input_api.AffectedFiles()):
1777 return [output_api.PresubmitError(
1778 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1779 'automated system based on what\'s in DEPS and your changes will be\n'
1780 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501781 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1782 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441783 'for more information')]
1784 return []
1785
1786
tandriief664692014-09-23 14:51:471787def _CheckValidHostsInDEPS(input_api, output_api):
1788 """Checks that DEPS file deps are from allowed_hosts."""
1789 # Run only if DEPS file has been modified to annoy fewer bystanders.
1790 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1791 return []
1792 # Outsource work to gclient verify
1793 try:
John Budorickf20c0042019-04-25 23:23:401794 gclient_path = input_api.os_path.join(
1795 input_api.PresubmitLocalPath(),
1796 'third_party', 'depot_tools', 'gclient.py')
1797 input_api.subprocess.check_output(
1798 [input_api.python_executable, gclient_path, 'verify'],
1799 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471800 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201801 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471802 return [output_api.PresubmitError(
1803 'DEPS file must have only git dependencies.',
1804 long_text=error.output)]
1805
1806
Mario Sanchez Prada2472cab2019-09-18 10:58:311807def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1808 type_name, message):
1809 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1810
1811 Returns an string composed of the name of the file, the line number where the
1812 match has been found and the additional text passed as |message| in case the
1813 target type name matches the text inside the line passed as parameter.
1814 """
1815 matched = False
1816 if type_name[0:1] == '/':
1817 regex = type_name[1:]
1818 if input_api.re.search(regex, line):
1819 matched = True
1820 elif type_name in line:
1821 matched = True
1822
1823 result = []
1824 if matched:
1825 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1826 for message_line in message:
1827 result.append(' %s' % message_line)
1828
1829 return result
1830
1831
[email protected]127f18ec2012-06-16 05:05:591832def _CheckNoBannedFunctions(input_api, output_api):
1833 """Make sure that banned functions are not used."""
1834 warnings = []
1835 errors = []
1836
wnwenbdc444e2016-05-25 13:44:151837 def IsBlacklisted(affected_file, blacklist):
1838 local_path = affected_file.LocalPath()
1839 for item in blacklist:
1840 if input_api.re.match(item, local_path):
1841 return True
1842 return False
1843
Peter K. Lee6c03ccff2019-07-15 14:40:051844 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541845 local_path = affected_file.LocalPath()
1846 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1847 return False
1848 basename = input_api.os_path.basename(local_path)
1849 if 'ios' in basename.split('_'):
1850 return True
1851 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1852 if sep and 'ios' in local_path.split(sep):
1853 return True
1854 return False
1855
wnwenbdc444e2016-05-25 13:44:151856 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311857 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1858 func_name, message)
1859 if problems:
wnwenbdc444e2016-05-25 13:44:151860 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311861 errors.extend(problems)
1862 else:
1863 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151864
Eric Stevensona9a980972017-09-23 00:04:411865 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1866 for f in input_api.AffectedFiles(file_filter=file_filter):
1867 for line_num, line in f.ChangedContents():
1868 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1869 CheckForMatch(f, line_num, line, func_name, message, error)
1870
[email protected]127f18ec2012-06-16 05:05:591871 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
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_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151875 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591876
Peter K. Lee6c03ccff2019-07-15 14:40:051877 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541878 for line_num, line in f.ChangedContents():
1879 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1880 CheckForMatch(f, line_num, line, func_name, message, error)
1881
Peter K. Lee6c03ccff2019-07-15 14:40:051882 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1883 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1884 for line_num, line in f.ChangedContents():
1885 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1886 CheckForMatch(f, line_num, line, func_name, message, error)
1887
[email protected]127f18ec2012-06-16 05:05:591888 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1889 for f in input_api.AffectedFiles(file_filter=file_filter):
1890 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491891 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491892 if IsBlacklisted(f, excluded_paths):
1893 continue
wnwenbdc444e2016-05-25 13:44:151894 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591895
1896 result = []
1897 if (warnings):
1898 result.append(output_api.PresubmitPromptWarning(
1899 'Banned functions were used.\n' + '\n'.join(warnings)))
1900 if (errors):
1901 result.append(output_api.PresubmitError(
1902 'Banned functions were used.\n' + '\n'.join(errors)))
1903 return result
1904
1905
Michael Thiessen44457642020-02-06 00:24:151906def _CheckAndroidNoBannedImports(input_api, output_api):
1907 """Make sure that banned java imports are not used."""
1908 errors = []
1909
1910 def IsException(path, exceptions):
1911 for exception in exceptions:
1912 if (path.startswith(exception)):
1913 return True
1914 return False
1915
1916 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1917 for f in input_api.AffectedFiles(file_filter=file_filter):
1918 for line_num, line in f.ChangedContents():
1919 for import_name, message, exceptions in _BANNED_JAVA_IMPORTS:
1920 if IsException(f.LocalPath(), exceptions):
1921 continue;
1922 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1923 'import ' + import_name, message)
1924 if problems:
1925 errors.extend(problems)
1926 result = []
1927 if (errors):
1928 result.append(output_api.PresubmitError(
1929 'Banned imports were used.\n' + '\n'.join(errors)))
1930 return result
1931
1932
Mario Sanchez Prada2472cab2019-09-18 10:58:311933def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1934 """Make sure that old Mojo types are not used."""
1935 warnings = []
Mario Sanchez Pradacec9cef2019-12-15 11:54:571936 errors = []
Mario Sanchez Prada2472cab2019-09-18 10:58:311937
Mario Sanchez Pradaaab91382019-12-19 08:57:091938 # For any path that is not an "ok" or an "error" path, a warning will be
1939 # raised if deprecated mojo types are found.
1940 ok_paths = ['components/arc']
1941 error_paths = ['third_party/blink', 'content']
1942
Mario Sanchez Prada2472cab2019-09-18 10:58:311943 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1944 for f in input_api.AffectedFiles(file_filter=file_filter):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571945 # Don't check //components/arc, not yet migrated (see crrev.com/c/1868870).
Mario Sanchez Pradaaab91382019-12-19 08:57:091946 if any(map(lambda path: f.LocalPath().startswith(path), ok_paths)):
Mario Sanchez Prada2472cab2019-09-18 10:58:311947 continue
1948
1949 for line_num, line in f.ChangedContents():
1950 for func_name, message in _DEPRECATED_MOJO_TYPES:
1951 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1952 func_name, message)
Mario Sanchez Pradacec9cef2019-12-15 11:54:571953
Mario Sanchez Prada2472cab2019-09-18 10:58:311954 if problems:
Mario Sanchez Pradaaab91382019-12-19 08:57:091955 # Raise errors inside |error_paths| and warnings everywhere else.
1956 if any(map(lambda path: f.LocalPath().startswith(path), error_paths)):
Mario Sanchez Pradacec9cef2019-12-15 11:54:571957 errors.extend(problems)
1958 else:
Mario Sanchez Prada2472cab2019-09-18 10:58:311959 warnings.extend(problems)
1960
1961 result = []
1962 if (warnings):
1963 result.append(output_api.PresubmitPromptWarning(
1964 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
Mario Sanchez Pradacec9cef2019-12-15 11:54:571965 if (errors):
1966 result.append(output_api.PresubmitError(
1967 'Banned Mojo types were used.\n' + '\n'.join(errors)))
Mario Sanchez Prada2472cab2019-09-18 10:58:311968 return result
1969
1970
[email protected]6c063c62012-07-11 19:11:061971def _CheckNoPragmaOnce(input_api, output_api):
1972 """Make sure that banned functions are not used."""
1973 files = []
1974 pattern = input_api.re.compile(r'^#pragma\s+once',
1975 input_api.re.MULTILINE)
1976 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1977 if not f.LocalPath().endswith('.h'):
1978 continue
1979 contents = input_api.ReadFile(f)
1980 if pattern.search(contents):
1981 files.append(f)
1982
1983 if files:
1984 return [output_api.PresubmitError(
1985 'Do not use #pragma once in header files.\n'
1986 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1987 files)]
1988 return []
1989
[email protected]127f18ec2012-06-16 05:05:591990
[email protected]e7479052012-09-19 00:26:121991def _CheckNoTrinaryTrueFalse(input_api, output_api):
1992 """Checks to make sure we don't introduce use of foo ? true : false."""
1993 problems = []
1994 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1995 for f in input_api.AffectedFiles():
1996 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1997 continue
1998
1999 for line_num, line in f.ChangedContents():
2000 if pattern.match(line):
2001 problems.append(' %s:%d' % (f.LocalPath(), line_num))
2002
2003 if not problems:
2004 return []
2005 return [output_api.PresubmitPromptWarning(
2006 'Please consider avoiding the "? true : false" pattern if possible.\n' +
2007 '\n'.join(problems))]
2008
2009
[email protected]55f9f382012-07-31 11:02:182010def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:282011 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:182012 change. Breaking - rules is an error, breaking ! rules is a
2013 warning.
2014 """
mohan.reddyf21db962014-10-16 12:26:472015 import sys
[email protected]55f9f382012-07-31 11:02:182016 # We need to wait until we have an input_api object and use this
2017 # roundabout construct to import checkdeps because this file is
2018 # eval-ed and thus doesn't have __file__.
2019 original_sys_path = sys.path
2020 try:
2021 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:472022 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:182023 import checkdeps
[email protected]55f9f382012-07-31 11:02:182024 from rules import Rule
2025 finally:
2026 # Restore sys.path to what it was before.
2027 sys.path = original_sys_path
2028
2029 added_includes = []
rhalavati08acd232017-04-03 07:23:282030 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:242031 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:182032 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:062033 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502034 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082035 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062036 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502037 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082038 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062039 elif _IsJavaFile(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_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182042
[email protected]26385172013-05-09 23:11:352043 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182044
2045 error_descriptions = []
2046 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282047 error_subjects = set()
2048 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182049 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2050 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082051 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182052 description_with_path = '%s\n %s' % (path, rule_description)
2053 if rule_type == Rule.DISALLOW:
2054 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282055 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182056 else:
2057 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282058 warning_subjects.add("#includes")
2059
2060 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2061 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082062 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282063 description_with_path = '%s\n %s' % (path, rule_description)
2064 if rule_type == Rule.DISALLOW:
2065 error_descriptions.append(description_with_path)
2066 error_subjects.add("imports")
2067 else:
2068 warning_descriptions.append(description_with_path)
2069 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182070
Jinsuk Kim5a092672017-10-24 22:42:242071 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022072 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082073 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242074 description_with_path = '%s\n %s' % (path, rule_description)
2075 if rule_type == Rule.DISALLOW:
2076 error_descriptions.append(description_with_path)
2077 error_subjects.add("imports")
2078 else:
2079 warning_descriptions.append(description_with_path)
2080 warning_subjects.add("imports")
2081
[email protected]55f9f382012-07-31 11:02:182082 results = []
2083 if error_descriptions:
2084 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282085 'You added one or more %s that violate checkdeps rules.'
2086 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182087 error_descriptions))
2088 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422089 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282090 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182091 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282092 '%s? See relevant DEPS file(s) for details and contacts.' %
2093 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182094 warning_descriptions))
2095 return results
2096
2097
[email protected]fbcafe5a2012-08-08 15:31:222098def _CheckFilePermissions(input_api, output_api):
2099 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152100 if input_api.platform == 'win32':
2101 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292102 checkperms_tool = input_api.os_path.join(
2103 input_api.PresubmitLocalPath(),
2104 'tools', 'checkperms', 'checkperms.py')
2105 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472106 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392107 with input_api.CreateTemporaryFile() as file_list:
2108 for f in input_api.AffectedFiles():
2109 # checkperms.py file/directory arguments must be relative to the
2110 # repository.
2111 file_list.write(f.LocalPath() + '\n')
2112 file_list.close()
2113 args += ['--file-list', file_list.name]
2114 try:
2115 input_api.subprocess.check_output(args)
2116 return []
2117 except input_api.subprocess.CalledProcessError as error:
2118 return [output_api.PresubmitError(
2119 'checkperms.py failed:',
2120 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222121
2122
robertocn832f5992017-01-04 19:01:302123def _CheckTeamTags(input_api, output_api):
2124 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2125 checkteamtags_tool = input_api.os_path.join(
2126 input_api.PresubmitLocalPath(),
2127 'tools', 'checkteamtags', 'checkteamtags.py')
2128 args = [input_api.python_executable, checkteamtags_tool,
2129 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222130 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302131 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2132 'OWNERS']
2133 try:
2134 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052135 warnings = input_api.subprocess.check_output(args + files).splitlines()
2136 if warnings:
2137 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302138 return []
2139 except input_api.subprocess.CalledProcessError as error:
2140 return [output_api.PresubmitError(
2141 'checkteamtags.py failed:',
2142 long_text=error.output)]
2143
2144
[email protected]c8278b32012-10-30 20:35:492145def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2146 """Makes sure we don't include ui/aura/window_property.h
2147 in header files.
2148 """
2149 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2150 errors = []
2151 for f in input_api.AffectedFiles():
2152 if not f.LocalPath().endswith('.h'):
2153 continue
2154 for line_num, line in f.ChangedContents():
2155 if pattern.match(line):
2156 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2157
2158 results = []
2159 if errors:
2160 results.append(output_api.PresubmitError(
2161 'Header files should not include ui/aura/window_property.h', errors))
2162 return results
2163
2164
[email protected]70ca77752012-11-20 03:45:032165def _CheckForVersionControlConflictsInFile(input_api, f):
2166 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2167 errors = []
2168 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162169 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232170 # First-level headers in markdown look a lot like version control
2171 # conflict markers. http://daringfireball.net/projects/markdown/basics
2172 continue
[email protected]70ca77752012-11-20 03:45:032173 if pattern.match(line):
2174 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2175 return errors
2176
2177
2178def _CheckForVersionControlConflicts(input_api, output_api):
2179 """Usually this is not intentional and will cause a compile failure."""
2180 errors = []
2181 for f in input_api.AffectedFiles():
2182 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2183
2184 results = []
2185 if errors:
2186 results.append(output_api.PresubmitError(
2187 'Version control conflict markers found, please resolve.', errors))
2188 return results
2189
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202190
estadee17314a02017-01-12 16:22:162191def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2192 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2193 errors = []
2194 for f in input_api.AffectedFiles():
2195 for line_num, line in f.ChangedContents():
2196 if pattern.search(line):
2197 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2198
2199 results = []
2200 if errors:
2201 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502202 'Found Google support URL addressed by answer number. Please replace '
2203 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162204 return results
2205
[email protected]70ca77752012-11-20 03:45:032206
[email protected]06e6d0ff2012-12-11 01:36:442207def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2208 def FilterFile(affected_file):
2209 """Filter function for use with input_api.AffectedSourceFiles,
2210 below. This filters out everything except non-test files from
2211 top-level directories that generally speaking should not hard-code
2212 service URLs (e.g. src/android_webview/, src/content/ and others).
2213 """
2214 return input_api.FilterSourceFile(
2215 affected_file,
Egor Paskoce145c42018-09-28 19:31:042216 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442217 black_list=(_EXCLUDED_PATHS +
2218 _TEST_CODE_EXCLUDED_PATHS +
2219 input_api.DEFAULT_BLACK_LIST))
2220
reillyi38965732015-11-16 18:27:332221 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2222 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462223 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2224 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442225 problems = [] # items are (filename, line_number, line)
2226 for f in input_api.AffectedSourceFiles(FilterFile):
2227 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462228 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442229 problems.append((f.LocalPath(), line_num, line))
2230
2231 if problems:
[email protected]f7051d52013-04-02 18:31:422232 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442233 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582234 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442235 [' %s:%d: %s' % (
2236 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032237 else:
2238 return []
[email protected]06e6d0ff2012-12-11 01:36:442239
2240
James Cook6b6597c2019-11-06 22:05:292241def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2242 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2243 def FileFilter(affected_file):
2244 """Includes directories known to be Chrome OS only."""
2245 return input_api.FilterSourceFile(
2246 affected_file,
2247 white_list=('^ash/',
2248 '^chromeos/', # Top-level src/chromeos.
2249 '/chromeos/', # Any path component.
2250 '^components/arc',
2251 '^components/exo'),
2252 black_list=(input_api.DEFAULT_BLACK_LIST))
2253
2254 prefs = []
2255 priority_prefs = []
2256 for f in input_api.AffectedFiles(file_filter=FileFilter):
2257 for line_num, line in f.ChangedContents():
2258 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2259 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2260 prefs.append(' %s' % line)
2261 if input_api.re.search(
2262 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2263 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2264 priority_prefs.append(' %s' % line)
2265
2266 results = []
2267 if (prefs):
2268 results.append(output_api.PresubmitPromptWarning(
2269 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2270 'by browser sync settings. If these prefs should be controlled by OS '
2271 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2272 if (priority_prefs):
2273 results.append(output_api.PresubmitPromptWarning(
2274 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2275 'controlled by browser sync settings. If these prefs should be '
2276 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2277 'instead.\n' + '\n'.join(prefs)))
2278 return results
2279
2280
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492281# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272282def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2283 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312284 The native_client_sdk directory is excluded because it has auto-generated PNG
2285 files for documentation.
[email protected]d2530012013-01-25 16:39:272286 """
[email protected]d2530012013-01-25 16:39:272287 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492288 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042289 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312290 file_filter = lambda f: input_api.FilterSourceFile(
2291 f, white_list=white_list, black_list=black_list)
2292 for f in input_api.AffectedFiles(include_deletes=False,
2293 file_filter=file_filter):
2294 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272295
2296 results = []
2297 if errors:
2298 results.append(output_api.PresubmitError(
2299 'The name of PNG files should not have abbreviations. \n'
2300 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2301 'Contact [email protected] if you have questions.', errors))
2302 return results
2303
2304
Daniel Cheng4dcdb6b2017-04-13 08:30:172305def _ExtractAddRulesFromParsedDeps(parsed_deps):
2306 """Extract the rules that add dependencies from a parsed DEPS file.
2307
2308 Args:
2309 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2310 add_rules = set()
2311 add_rules.update([
2312 rule[1:] for rule in parsed_deps.get('include_rules', [])
2313 if rule.startswith('+') or rule.startswith('!')
2314 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502315 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172316 {}).iteritems():
2317 add_rules.update([
2318 rule[1:] for rule in rules
2319 if rule.startswith('+') or rule.startswith('!')
2320 ])
2321 return add_rules
2322
2323
2324def _ParseDeps(contents):
2325 """Simple helper for parsing DEPS files."""
2326 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172327 class _VarImpl:
2328
2329 def __init__(self, local_scope):
2330 self._local_scope = local_scope
2331
2332 def Lookup(self, var_name):
2333 """Implements the Var syntax."""
2334 try:
2335 return self._local_scope['vars'][var_name]
2336 except KeyError:
2337 raise Exception('Var is not defined: %s' % var_name)
2338
2339 local_scope = {}
2340 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172341 'Var': _VarImpl(local_scope).Lookup,
2342 }
2343 exec contents in global_scope, local_scope
2344 return local_scope
2345
2346
2347def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082348 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412349 a set of DEPS entries that we should look up.
2350
2351 For a directory (rather than a specific filename) we fake a path to
2352 a specific filename by adding /DEPS. This is chosen as a file that
2353 will seldom or never be subject to per-file include_rules.
2354 """
[email protected]2b438d62013-11-14 17:54:142355 # We ignore deps entries on auto-generated directories.
2356 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082357
Daniel Cheng4dcdb6b2017-04-13 08:30:172358 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2359 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2360
2361 added_deps = new_deps.difference(old_deps)
2362
[email protected]2b438d62013-11-14 17:54:142363 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172364 for added_dep in added_deps:
2365 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2366 continue
2367 # Assume that a rule that ends in .h is a rule for a specific file.
2368 if added_dep.endswith('.h'):
2369 results.add(added_dep)
2370 else:
2371 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082372 return results
2373
2374
[email protected]e871964c2013-05-13 14:14:552375def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2376 """When a dependency prefixed with + is added to a DEPS file, we
2377 want to make sure that the change is reviewed by an OWNER of the
2378 target file or directory, to avoid layering violations from being
2379 introduced. This check verifies that this happens.
2380 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172381 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242382
2383 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492384 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242385 for f in input_api.AffectedFiles(include_deletes=False,
2386 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552387 filename = input_api.os_path.basename(f.LocalPath())
2388 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172389 virtual_depended_on_files.update(_CalculateAddedDeps(
2390 input_api.os_path,
2391 '\n'.join(f.OldContents()),
2392 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552393
[email protected]e871964c2013-05-13 14:14:552394 if not virtual_depended_on_files:
2395 return []
2396
2397 if input_api.is_committing:
2398 if input_api.tbr:
2399 return [output_api.PresubmitNotifyResult(
2400 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272401 if input_api.dry_run:
2402 return [output_api.PresubmitNotifyResult(
2403 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552404 if not input_api.change.issue:
2405 return [output_api.PresubmitError(
2406 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402407 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552408 output = output_api.PresubmitError
2409 else:
2410 output = output_api.PresubmitNotifyResult
2411
2412 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502413 owner_email, reviewers = (
2414 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2415 input_api,
2416 owners_db.email_regexp,
2417 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552418
2419 owner_email = owner_email or input_api.change.author_email
2420
[email protected]de4f7d22013-05-23 14:27:462421 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512422 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462423 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552424 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2425 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412426
2427 # We strip the /DEPS part that was added by
2428 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2429 # directory.
2430 def StripDeps(path):
2431 start_deps = path.rfind('/DEPS')
2432 if start_deps != -1:
2433 return path[:start_deps]
2434 else:
2435 return path
2436 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552437 for path in missing_files]
2438
2439 if unapproved_dependencies:
2440 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152441 output('You need LGTM from owners of depends-on paths in DEPS that were '
2442 'modified in this CL:\n %s' %
2443 '\n '.join(sorted(unapproved_dependencies)))]
2444 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2445 output_list.append(output(
2446 'Suggested missing target path OWNERS:\n %s' %
2447 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552448 return output_list
2449
2450 return []
2451
2452
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492453# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402454def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492455 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402456 black_list = (_EXCLUDED_PATHS +
2457 _TEST_CODE_EXCLUDED_PATHS +
2458 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042459 (r"^base[\\/]logging\.h$",
2460 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222461 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042462 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2463 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2464 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122465 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182466 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152467 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032468 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152469 r"^chrome[\\/]chrome_cleaner[\\/].*",
2470 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2471 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042472 r"^chromecast[\\/]",
2473 r"^cloud_print[\\/]",
2474 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482475 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042476 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312477 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042478 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462479 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042480 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462481 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042482 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252483 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042484 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2485 r"^courgette[\\/]courgette_tool\.cc$",
2486 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272487 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002488 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332489 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042490 r"^ipc[\\/]ipc_logging\.cc$",
2491 r"^native_client_sdk[\\/]",
2492 r"^remoting[\\/]base[\\/]logging\.h$",
2493 r"^remoting[\\/]host[\\/].*",
2494 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062495 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332496 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042497 r"^tools[\\/]",
2498 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2499 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332500 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402501 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492502 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402503
thomasanderson625d3932017-03-29 07:16:582504 log_info = set([])
2505 printf = set([])
[email protected]85218562013-11-22 07:41:402506
2507 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582508 for _, line in f.ChangedContents():
2509 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2510 log_info.add(f.LocalPath())
2511 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2512 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372513
thomasanderson625d3932017-03-29 07:16:582514 if input_api.re.search(r"\bprintf\(", line):
2515 printf.add(f.LocalPath())
2516 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2517 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402518
2519 if log_info:
2520 return [output_api.PresubmitError(
2521 'These files spam the console log with LOG(INFO):',
2522 items=log_info)]
2523 if printf:
2524 return [output_api.PresubmitError(
2525 'These files spam the console log with printf/fprintf:',
2526 items=printf)]
2527 return []
2528
2529
[email protected]49aa76a2013-12-04 06:59:162530def _CheckForAnonymousVariables(input_api, output_api):
2531 """These types are all expected to hold locks while in scope and
2532 so should never be anonymous (which causes them to be immediately
2533 destroyed)."""
2534 they_who_must_be_named = [
2535 'base::AutoLock',
2536 'base::AutoReset',
2537 'base::AutoUnlock',
2538 'SkAutoAlphaRestore',
2539 'SkAutoBitmapShaderInstall',
2540 'SkAutoBlitterChoose',
2541 'SkAutoBounderCommit',
2542 'SkAutoCallProc',
2543 'SkAutoCanvasRestore',
2544 'SkAutoCommentBlock',
2545 'SkAutoDescriptor',
2546 'SkAutoDisableDirectionCheck',
2547 'SkAutoDisableOvalCheck',
2548 'SkAutoFree',
2549 'SkAutoGlyphCache',
2550 'SkAutoHDC',
2551 'SkAutoLockColors',
2552 'SkAutoLockPixels',
2553 'SkAutoMalloc',
2554 'SkAutoMaskFreeImage',
2555 'SkAutoMutexAcquire',
2556 'SkAutoPathBoundsUpdate',
2557 'SkAutoPDFRelease',
2558 'SkAutoRasterClipValidate',
2559 'SkAutoRef',
2560 'SkAutoTime',
2561 'SkAutoTrace',
2562 'SkAutoUnref',
2563 ]
2564 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2565 # bad: base::AutoLock(lock.get());
2566 # not bad: base::AutoLock lock(lock.get());
2567 bad_pattern = input_api.re.compile(anonymous)
2568 # good: new base::AutoLock(lock.get())
2569 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2570 errors = []
2571
2572 for f in input_api.AffectedFiles():
2573 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2574 continue
2575 for linenum, line in f.ChangedContents():
2576 if bad_pattern.search(line) and not good_pattern.search(line):
2577 errors.append('%s:%d' % (f.LocalPath(), linenum))
2578
2579 if errors:
2580 return [output_api.PresubmitError(
2581 'These lines create anonymous variables that need to be named:',
2582 items=errors)]
2583 return []
2584
2585
Peter Kasting4844e46e2018-02-23 07:27:102586def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532587 # Returns whether |template_str| is of the form <T, U...> for some types T
2588 # and U. Assumes that |template_str| is already in the form <...>.
2589 def HasMoreThanOneArg(template_str):
2590 # Level of <...> nesting.
2591 nesting = 0
2592 for c in template_str:
2593 if c == '<':
2594 nesting += 1
2595 elif c == '>':
2596 nesting -= 1
2597 elif c == ',' and nesting == 1:
2598 return True
2599 return False
2600
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492601 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102602 sources = lambda affected_file: input_api.FilterSourceFile(
2603 affected_file,
2604 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2605 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492606 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552607
2608 # Pattern to capture a single "<...>" block of template arguments. It can
2609 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2610 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2611 # latter would likely require counting that < and > match, which is not
2612 # expressible in regular languages. Should the need arise, one can introduce
2613 # limited counting (matching up to a total number of nesting depth), which
2614 # should cover all practical cases for already a low nesting limit.
2615 template_arg_pattern = (
2616 r'<[^>]*' # Opening block of <.
2617 r'>([^<]*>)?') # Closing block of >.
2618 # Prefix expressing that whatever follows is not already inside a <...>
2619 # block.
2620 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102621 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552622 not_inside_template_arg_pattern
2623 + r'\bstd::unique_ptr'
2624 + template_arg_pattern
2625 + r'\(\)')
2626
2627 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2628 template_arg_no_array_pattern = (
2629 r'<[^>]*[^]]' # Opening block of <.
2630 r'>([^(<]*[^]]>)?') # Closing block of >.
2631 # Prefix saying that what follows is the start of an expression.
2632 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2633 # Suffix saying that what follows are call parentheses with a non-empty list
2634 # of arguments.
2635 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532636 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552637 return_construct_pattern = input_api.re.compile(
2638 start_of_expr_pattern
2639 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532640 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552641 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532642 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552643 + nonempty_arg_list_pattern)
2644
Vaclav Brozek851d9602018-04-04 16:13:052645 problems_constructor = []
2646 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102647 for f in input_api.AffectedSourceFiles(sources):
2648 for line_number, line in f.ChangedContents():
2649 # Disallow:
2650 # return std::unique_ptr<T>(foo);
2651 # bar = std::unique_ptr<T>(foo);
2652 # But allow:
2653 # return std::unique_ptr<T[]>(foo);
2654 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532655 # And also allow cases when the second template argument is present. Those
2656 # cases cannot be handled by std::make_unique:
2657 # return std::unique_ptr<T, U>(foo);
2658 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052659 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532660 return_construct_result = return_construct_pattern.search(line)
2661 if return_construct_result and not HasMoreThanOneArg(
2662 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052663 problems_constructor.append(
2664 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102665 # Disallow:
2666 # std::unique_ptr<T>()
2667 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052668 problems_nullptr.append(
2669 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2670
2671 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162672 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052673 errors.append(output_api.PresubmitError(
2674 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162675 problems_nullptr))
2676 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052677 errors.append(output_api.PresubmitError(
2678 'The following files use explicit std::unique_ptr constructor.'
2679 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162680 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102681 return errors
2682
2683
[email protected]999261d2014-03-03 20:08:082684def _CheckUserActionUpdate(input_api, output_api):
2685 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522686 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082687 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522688 # If actions.xml is already included in the changelist, the PRESUBMIT
2689 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082690 return []
2691
[email protected]999261d2014-03-03 20:08:082692 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2693 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522694 current_actions = None
[email protected]999261d2014-03-03 20:08:082695 for f in input_api.AffectedFiles(file_filter=file_filter):
2696 for line_num, line in f.ChangedContents():
2697 match = input_api.re.search(action_re, line)
2698 if match:
[email protected]2f92dec2014-03-07 19:21:522699 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2700 # loaded only once.
2701 if not current_actions:
2702 with open('tools/metrics/actions/actions.xml') as actions_f:
2703 current_actions = actions_f.read()
2704 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082705 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522706 action = 'name="{0}"'.format(action_name)
2707 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082708 return [output_api.PresubmitPromptWarning(
2709 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522710 'tools/metrics/actions/actions.xml. Please run '
2711 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082712 % (f.LocalPath(), line_num, action_name))]
2713 return []
2714
2715
Daniel Cheng13ca61a882017-08-25 15:11:252716def _ImportJSONCommentEater(input_api):
2717 import sys
2718 sys.path = sys.path + [input_api.os_path.join(
2719 input_api.PresubmitLocalPath(),
2720 'tools', 'json_comment_eater')]
2721 import json_comment_eater
2722 return json_comment_eater
2723
2724
[email protected]99171a92014-06-03 08:44:472725def _GetJSONParseError(input_api, filename, eat_comments=True):
2726 try:
2727 contents = input_api.ReadFile(filename)
2728 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252729 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132730 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472731
2732 input_api.json.loads(contents)
2733 except ValueError as e:
2734 return e
2735 return None
2736
2737
2738def _GetIDLParseError(input_api, filename):
2739 try:
2740 contents = input_api.ReadFile(filename)
2741 idl_schema = input_api.os_path.join(
2742 input_api.PresubmitLocalPath(),
2743 'tools', 'json_schema_compiler', 'idl_schema.py')
2744 process = input_api.subprocess.Popen(
2745 [input_api.python_executable, idl_schema],
2746 stdin=input_api.subprocess.PIPE,
2747 stdout=input_api.subprocess.PIPE,
2748 stderr=input_api.subprocess.PIPE,
2749 universal_newlines=True)
2750 (_, error) = process.communicate(input=contents)
2751 return error or None
2752 except ValueError as e:
2753 return e
2754
2755
2756def _CheckParseErrors(input_api, output_api):
2757 """Check that IDL and JSON files do not contain syntax errors."""
2758 actions = {
2759 '.idl': _GetIDLParseError,
2760 '.json': _GetJSONParseError,
2761 }
[email protected]99171a92014-06-03 08:44:472762 # Most JSON files are preprocessed and support comments, but these do not.
2763 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042764 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472765 ]
2766 # Only run IDL checker on files in these directories.
2767 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042768 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2769 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472770 ]
2771
2772 def get_action(affected_file):
2773 filename = affected_file.LocalPath()
2774 return actions.get(input_api.os_path.splitext(filename)[1])
2775
[email protected]99171a92014-06-03 08:44:472776 def FilterFile(affected_file):
2777 action = get_action(affected_file)
2778 if not action:
2779 return False
2780 path = affected_file.LocalPath()
2781
Sean Kau46e29bc2017-08-28 16:31:162782 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472783 return False
2784
2785 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162786 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472787 return False
2788 return True
2789
2790 results = []
2791 for affected_file in input_api.AffectedFiles(
2792 file_filter=FilterFile, include_deletes=False):
2793 action = get_action(affected_file)
2794 kwargs = {}
2795 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162796 _MatchesFile(input_api, json_no_comments_patterns,
2797 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472798 kwargs['eat_comments'] = False
2799 parse_error = action(input_api,
2800 affected_file.AbsoluteLocalPath(),
2801 **kwargs)
2802 if parse_error:
2803 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2804 (affected_file.LocalPath(), parse_error)))
2805 return results
2806
2807
[email protected]760deea2013-12-10 19:33:492808def _CheckJavaStyle(input_api, output_api):
2809 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472810 import sys
[email protected]760deea2013-12-10 19:33:492811 original_sys_path = sys.path
2812 try:
2813 sys.path = sys.path + [input_api.os_path.join(
2814 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2815 import checkstyle
2816 finally:
2817 # Restore sys.path to what it was before.
2818 sys.path = original_sys_path
2819
2820 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092821 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512822 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492823
2824
Nate Fischerdfd9812e2019-07-18 22:03:002825def _CheckPythonDevilInit(input_api, output_api):
2826 """Checks to make sure devil is initialized correctly in python scripts."""
2827 script_common_initialize_pattern = input_api.re.compile(
2828 r'script_common\.InitializeEnvironment\(')
2829 devil_env_config_initialize = input_api.re.compile(
2830 r'devil_env\.config\.Initialize\(')
2831
2832 errors = []
2833
2834 sources = lambda affected_file: input_api.FilterSourceFile(
2835 affected_file,
2836 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2837 (r'^build[\\/]android[\\/]devil_chromium\.py',
2838 r'^third_party[\\/].*',)),
2839 white_list=[r'.*\.py$'])
2840
2841 for f in input_api.AffectedSourceFiles(sources):
2842 for line_num, line in f.ChangedContents():
2843 if (script_common_initialize_pattern.search(line) or
2844 devil_env_config_initialize.search(line)):
2845 errors.append("%s:%d" % (f.LocalPath(), line_num))
2846
2847 results = []
2848
2849 if errors:
2850 results.append(output_api.PresubmitError(
2851 'Devil initialization should always be done using '
2852 'devil_chromium.Initialize() in the chromium project, to use better '
2853 'defaults for dependencies (ex. up-to-date version of adb).',
2854 errors))
2855
2856 return results
2857
2858
Sean Kau46e29bc2017-08-28 16:31:162859def _MatchesFile(input_api, patterns, path):
2860 for pattern in patterns:
2861 if input_api.re.search(pattern, path):
2862 return True
2863 return False
2864
2865
Daniel Cheng7052cdf2017-11-21 19:23:292866def _GetOwnersFilesToCheckForIpcOwners(input_api):
2867 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172868
Daniel Cheng7052cdf2017-11-21 19:23:292869 Returns:
2870 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2871 contain to cover IPC-related files with noparent reviewer rules.
2872 """
2873 # Whether or not a file affects IPC is (mostly) determined by a simple list
2874 # of filename patterns.
dchenge07de812016-06-20 19:27:172875 file_patterns = [
palmerb19a0932017-01-24 04:00:312876 # Legacy IPC:
dchenge07de812016-06-20 19:27:172877 '*_messages.cc',
2878 '*_messages*.h',
2879 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312880 # Mojo IPC:
dchenge07de812016-06-20 19:27:172881 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472882 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172883 '*_struct_traits*.*',
2884 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312885 '*.typemap',
2886 # Android native IPC:
2887 '*.aidl',
2888 # Blink uses a different file naming convention:
2889 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472890 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172891 '*StructTraits*.*',
2892 '*TypeConverter*.*',
2893 ]
2894
scottmg7a6ed5ba2016-11-04 18:22:042895 # These third_party directories do not contain IPCs, but contain files
2896 # matching the above patterns, which trigger false positives.
2897 exclude_paths = [
2898 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162899 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232900 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292901 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542902 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162903 # These files are just used to communicate between class loaders running
2904 # in the same process.
2905 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
Mugdha Lakhani6230b962020-01-13 13:00:572906 'weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/*',
2907
scottmg7a6ed5ba2016-11-04 18:22:042908 ]
2909
dchenge07de812016-06-20 19:27:172910 # Dictionary mapping an OWNERS file path to Patterns.
2911 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2912 # rules ) to a PatternEntry.
2913 # PatternEntry is a dictionary with two keys:
2914 # - 'files': the files that are matched by this pattern
2915 # - 'rules': the per-file rules needed for this pattern
2916 # For example, if we expect OWNERS file to contain rules for *.mojom and
2917 # *_struct_traits*.*, Patterns might look like this:
2918 # {
2919 # '*.mojom': {
2920 # 'files': ...,
2921 # 'rules': [
2922 # 'per-file *.mojom=set noparent',
2923 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2924 # ],
2925 # },
2926 # '*_struct_traits*.*': {
2927 # 'files': ...,
2928 # 'rules': [
2929 # 'per-file *_struct_traits*.*=set noparent',
2930 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2931 # ],
2932 # },
2933 # }
2934 to_check = {}
2935
Daniel Cheng13ca61a882017-08-25 15:11:252936 def AddPatternToCheck(input_file, pattern):
2937 owners_file = input_api.os_path.join(
2938 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2939 if owners_file not in to_check:
2940 to_check[owners_file] = {}
2941 if pattern not in to_check[owners_file]:
2942 to_check[owners_file][pattern] = {
2943 'files': [],
2944 'rules': [
2945 'per-file %s=set noparent' % pattern,
2946 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2947 ]
2948 }
Vaclav Brozekd5de76a2018-03-17 07:57:502949 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252950
dchenge07de812016-06-20 19:27:172951 # Iterate through the affected files to see what we actually need to check
2952 # for. We should only nag patch authors about per-file rules if a file in that
2953 # directory would match that pattern. If a directory only contains *.mojom
2954 # files and no *_messages*.h files, we should only nag about rules for
2955 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252956 for f in input_api.AffectedFiles(include_deletes=False):
2957 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362958 # affected files for .json, .cc, and .h files which look like they contain
2959 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162960 if (f.LocalPath().endswith('.json') and
2961 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2962 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252963 json_comment_eater = _ImportJSONCommentEater(input_api)
2964 mostly_json_lines = '\n'.join(f.NewContents())
2965 # Comments aren't allowed in strict JSON, so filter them out.
2966 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432967 try:
2968 json_content = input_api.json.loads(json_lines)
2969 except:
2970 # There's another PRESUBMIT check that already verifies that JSON files
2971 # are not invalid, so no need to emit another warning here.
2972 continue
Daniel Cheng13ca61a882017-08-25 15:11:252973 if 'interface_provider_specs' in json_content:
2974 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362975 else:
2976 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2977 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2978 if (manifest_pattern.search(f.LocalPath()) and not
2979 test_manifest_pattern.search(f.LocalPath())):
2980 # We expect all actual service manifest files to contain at least one
2981 # qualified reference to service_manager::Manifest.
2982 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2983 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172984 for pattern in file_patterns:
2985 if input_api.fnmatch.fnmatch(
2986 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042987 skip = False
2988 for exclude in exclude_paths:
2989 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2990 skip = True
2991 break
2992 if skip:
2993 continue
Daniel Cheng13ca61a882017-08-25 15:11:252994 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172995 break
2996
Daniel Cheng7052cdf2017-11-21 19:23:292997 return to_check
2998
2999
3000def _CheckIpcOwners(input_api, output_api):
3001 """Checks that affected files involving IPC have an IPC OWNERS rule."""
3002 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
3003
3004 if to_check:
3005 # If there are any OWNERS files to check, there are IPC-related changes in
3006 # this CL. Auto-CC the review list.
3007 output_api.AppendCC('[email protected]')
3008
3009 # Go through the OWNERS files to check, filtering out rules that are already
3010 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:173011 for owners_file, patterns in to_check.iteritems():
3012 try:
3013 with file(owners_file) as f:
3014 lines = set(f.read().splitlines())
3015 for entry in patterns.itervalues():
3016 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
3017 ]
3018 except IOError:
3019 # No OWNERS file, so all the rules are definitely missing.
3020 continue
3021
3022 # All the remaining lines weren't found in OWNERS files, so emit an error.
3023 errors = []
3024 for owners_file, patterns in to_check.iteritems():
3025 missing_lines = []
3026 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:503027 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:173028 missing_lines.extend(entry['rules'])
3029 files.extend([' %s' % f.LocalPath() for f in entry['files']])
3030 if missing_lines:
3031 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:053032 'Because of the presence of files:\n%s\n\n'
3033 '%s needs the following %d lines added:\n\n%s' %
3034 ('\n'.join(files), owners_file, len(missing_lines),
3035 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173036
3037 results = []
3038 if errors:
vabrf5ce3bf92016-07-11 14:52:413039 if input_api.is_committing:
3040 output = output_api.PresubmitError
3041 else:
3042 output = output_api.PresubmitPromptWarning
3043 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593044 'Found OWNERS files that need to be updated for IPC security ' +
3045 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173046 long_text='\n\n'.join(errors)))
3047
3048 return results
3049
3050
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263051def _CheckSetNoParent(input_api, output_api):
3052 """Checks that set noparent is only used together with an OWNERS file in
3053 //build/OWNERS.setnoparent (see also
3054 //docs/code_reviews.md#owners-files-details)
3055 """
3056 errors = []
3057
3058 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3059 allowed_owners_files = set()
3060 with open(allowed_owners_files_file, 'r') as f:
3061 for line in f:
3062 line = line.strip()
3063 if not line or line.startswith('#'):
3064 continue
3065 allowed_owners_files.add(line)
3066
3067 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3068
3069 for f in input_api.AffectedFiles(include_deletes=False):
3070 if not f.LocalPath().endswith('OWNERS'):
3071 continue
3072
3073 found_owners_files = set()
3074 found_set_noparent_lines = dict()
3075
3076 # Parse the OWNERS file.
3077 for lineno, line in enumerate(f.NewContents(), 1):
3078 line = line.strip()
3079 if line.startswith('set noparent'):
3080 found_set_noparent_lines[''] = lineno
3081 if line.startswith('file://'):
3082 if line in allowed_owners_files:
3083 found_owners_files.add('')
3084 if line.startswith('per-file'):
3085 match = per_file_pattern.match(line)
3086 if match:
3087 glob = match.group(1).strip()
3088 directive = match.group(2).strip()
3089 if directive == 'set noparent':
3090 found_set_noparent_lines[glob] = lineno
3091 if directive.startswith('file://'):
3092 if directive in allowed_owners_files:
3093 found_owners_files.add(glob)
3094
3095 # Check that every set noparent line has a corresponding file:// line
3096 # listed in build/OWNERS.setnoparent.
3097 for set_noparent_line in found_set_noparent_lines:
3098 if set_noparent_line in found_owners_files:
3099 continue
3100 errors.append(' %s:%d' % (f.LocalPath(),
3101 found_set_noparent_lines[set_noparent_line]))
3102
3103 results = []
3104 if errors:
3105 if input_api.is_committing:
3106 output = output_api.PresubmitError
3107 else:
3108 output = output_api.PresubmitPromptWarning
3109 results.append(output(
3110 'Found the following "set noparent" restrictions in OWNERS files that '
3111 'do not include owners from build/OWNERS.setnoparent:',
3112 long_text='\n\n'.join(errors)))
3113 return results
3114
3115
jbriance9e12f162016-11-25 07:57:503116def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313117 """Checks that added or removed lines in non third party affected
3118 header files do not lead to new useless class or struct forward
3119 declaration.
jbriance9e12f162016-11-25 07:57:503120 """
3121 results = []
3122 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3123 input_api.re.MULTILINE)
3124 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3125 input_api.re.MULTILINE)
3126 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313127 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193128 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493129 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313130 continue
3131
jbriance9e12f162016-11-25 07:57:503132 if not f.LocalPath().endswith('.h'):
3133 continue
3134
3135 contents = input_api.ReadFile(f)
3136 fwd_decls = input_api.re.findall(class_pattern, contents)
3137 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3138
3139 useless_fwd_decls = []
3140 for decl in fwd_decls:
3141 count = sum(1 for _ in input_api.re.finditer(
3142 r'\b%s\b' % input_api.re.escape(decl), contents))
3143 if count == 1:
3144 useless_fwd_decls.append(decl)
3145
3146 if not useless_fwd_decls:
3147 continue
3148
3149 for line in f.GenerateScmDiff().splitlines():
3150 if (line.startswith('-') and not line.startswith('--') or
3151 line.startswith('+') and not line.startswith('++')):
3152 for decl in useless_fwd_decls:
3153 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3154 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243155 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503156 (f.LocalPath(), decl)))
3157 useless_fwd_decls.remove(decl)
3158
3159 return results
3160
Jinsong Fan91ebbbd2019-04-16 14:57:173161def _CheckAndroidDebuggableBuild(input_api, output_api):
3162 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3163 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3164 this is a debuggable build of Android.
3165 """
3166 build_type_check_pattern = input_api.re.compile(
3167 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3168
3169 errors = []
3170
3171 sources = lambda affected_file: input_api.FilterSourceFile(
3172 affected_file,
3173 black_list=(_EXCLUDED_PATHS +
3174 _TEST_CODE_EXCLUDED_PATHS +
3175 input_api.DEFAULT_BLACK_LIST +
3176 (r"^android_webview[\\/]support_library[\\/]"
3177 "boundary_interfaces[\\/]",
3178 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3179 r'^third_party[\\/].*',
3180 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3181 r"webview[\\/]chromium[\\/]License.*",)),
3182 white_list=[r'.*\.java$'])
3183
3184 for f in input_api.AffectedSourceFiles(sources):
3185 for line_num, line in f.ChangedContents():
3186 if build_type_check_pattern.search(line):
3187 errors.append("%s:%d" % (f.LocalPath(), line_num))
3188
3189 results = []
3190
3191 if errors:
3192 results.append(output_api.PresubmitPromptWarning(
3193 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3194 ' Please use BuildInfo.isDebugAndroid() instead.',
3195 errors))
3196
3197 return results
jbriance9e12f162016-11-25 07:57:503198
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493199# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293200def _CheckAndroidToastUsage(input_api, output_api):
3201 """Checks that code uses org.chromium.ui.widget.Toast instead of
3202 android.widget.Toast (Chromium Toast doesn't force hardware
3203 acceleration on low-end devices, saving memory).
3204 """
3205 toast_import_pattern = input_api.re.compile(
3206 r'^import android\.widget\.Toast;$')
3207
3208 errors = []
3209
3210 sources = lambda affected_file: input_api.FilterSourceFile(
3211 affected_file,
3212 black_list=(_EXCLUDED_PATHS +
3213 _TEST_CODE_EXCLUDED_PATHS +
3214 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043215 (r'^chromecast[\\/].*',
3216 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493217 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293218
3219 for f in input_api.AffectedSourceFiles(sources):
3220 for line_num, line in f.ChangedContents():
3221 if toast_import_pattern.search(line):
3222 errors.append("%s:%d" % (f.LocalPath(), line_num))
3223
3224 results = []
3225
3226 if errors:
3227 results.append(output_api.PresubmitError(
3228 'android.widget.Toast usage is detected. Android toasts use hardware'
3229 ' acceleration, and can be\ncostly on low-end devices. Please use'
3230 ' org.chromium.ui.widget.Toast instead.\n'
3231 'Contact [email protected] if you have any questions.',
3232 errors))
3233
3234 return results
3235
3236
dgnaa68d5e2015-06-10 10:08:223237def _CheckAndroidCrLogUsage(input_api, output_api):
3238 """Checks that new logs using org.chromium.base.Log:
3239 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513240 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223241 """
pkotwicza1dd0b002016-05-16 14:41:043242
torne89540622017-03-24 19:41:303243 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043244 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303245 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043246 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303247 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043248 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3249 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093250 # The customtabs_benchmark is a small app that does not depend on Chromium
3251 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043252 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043253 ]
3254
dgnaa68d5e2015-06-10 10:08:223255 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123256 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3257 class_in_base_pattern = input_api.re.compile(
3258 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3259 has_some_log_import_pattern = input_api.re.compile(
3260 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223261 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123262 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223263 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463264 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223265
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463266 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493267 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043268 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123269
dgnaa68d5e2015-06-10 10:08:223270 tag_decl_errors = []
3271 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123272 tag_errors = []
dgn38736db2015-09-18 19:20:513273 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123274 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223275
3276 for f in input_api.AffectedSourceFiles(sources):
3277 file_content = input_api.ReadFile(f)
3278 has_modified_logs = False
3279
3280 # Per line checks
dgn87d9fb62015-06-12 09:15:123281 if (cr_log_import_pattern.search(file_content) or
3282 (class_in_base_pattern.search(file_content) and
3283 not has_some_log_import_pattern.search(file_content))):
3284 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223285 for line_num, line in f.ChangedContents():
3286
3287 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123288 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223289 if match:
3290 has_modified_logs = True
3291
3292 # Make sure it uses "TAG"
3293 if not match.group('tag') == 'TAG':
3294 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123295 else:
3296 # Report non cr Log function calls in changed lines
3297 for line_num, line in f.ChangedContents():
3298 if log_call_pattern.search(line):
3299 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223300
3301 # Per file checks
3302 if has_modified_logs:
3303 # Make sure the tag is using the "cr" prefix and is not too long
3304 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513305 tag_name = match.group('name') if match else None
3306 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223307 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513308 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223309 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513310 elif '.' in tag_name:
3311 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223312
3313 results = []
3314 if tag_decl_errors:
3315 results.append(output_api.PresubmitPromptWarning(
3316 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513317 '"private static final String TAG = "<package tag>".\n'
3318 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223319 tag_decl_errors))
3320
3321 if tag_length_errors:
3322 results.append(output_api.PresubmitError(
3323 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513324 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223325 tag_length_errors))
3326
3327 if tag_errors:
3328 results.append(output_api.PresubmitPromptWarning(
3329 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3330 tag_errors))
3331
dgn87d9fb62015-06-12 09:15:123332 if util_log_errors:
dgn4401aa52015-04-29 16:26:173333 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123334 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3335 util_log_errors))
3336
dgn38736db2015-09-18 19:20:513337 if tag_with_dot_errors:
3338 results.append(output_api.PresubmitPromptWarning(
3339 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3340 tag_with_dot_errors))
3341
dgn4401aa52015-04-29 16:26:173342 return results
3343
3344
Yoland Yanb92fa522017-08-28 17:37:063345def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3346 """Checks that junit.framework.* is no longer used."""
3347 deprecated_junit_framework_pattern = input_api.re.compile(
3348 r'^import junit\.framework\..*;',
3349 input_api.re.MULTILINE)
3350 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493351 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063352 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133353 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063354 for line_num, line in f.ChangedContents():
3355 if deprecated_junit_framework_pattern.search(line):
3356 errors.append("%s:%d" % (f.LocalPath(), line_num))
3357
3358 results = []
3359 if errors:
3360 results.append(output_api.PresubmitError(
3361 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3362 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3363 ' if you have any question.', errors))
3364 return results
3365
3366
3367def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3368 """Checks that if new Java test classes have inheritance.
3369 Either the new test class is JUnit3 test or it is a JUnit4 test class
3370 with a base class, either case is undesirable.
3371 """
3372 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3373
3374 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493375 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063376 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133377 for f in input_api.AffectedFiles(file_filter=sources):
Yoland Yanb92fa522017-08-28 17:37:063378 if not f.OldContents():
3379 class_declaration_start_flag = False
3380 for line_num, line in f.ChangedContents():
3381 if class_declaration_pattern.search(line):
3382 class_declaration_start_flag = True
3383 if class_declaration_start_flag and ' extends ' in line:
3384 errors.append('%s:%d' % (f.LocalPath(), line_num))
3385 if '{' in line:
3386 class_declaration_start_flag = False
3387
3388 results = []
3389 if errors:
3390 results.append(output_api.PresubmitPromptWarning(
3391 'The newly created files include Test classes that inherits from base'
3392 ' class. Please do not use inheritance in JUnit4 tests or add new'
3393 ' JUnit3 tests. Contact [email protected] if you have any'
3394 ' questions.', errors))
3395 return results
3396
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203397
yolandyan45001472016-12-21 21:12:423398def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3399 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3400 deprecated_annotation_import_pattern = input_api.re.compile(
3401 r'^import android\.test\.suitebuilder\.annotation\..*;',
3402 input_api.re.MULTILINE)
3403 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493404 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423405 errors = []
Edward Lemur7bbfdf12020-01-15 02:06:133406 for f in input_api.AffectedFiles(file_filter=sources):
yolandyan45001472016-12-21 21:12:423407 for line_num, line in f.ChangedContents():
3408 if deprecated_annotation_import_pattern.search(line):
3409 errors.append("%s:%d" % (f.LocalPath(), line_num))
3410
3411 results = []
3412 if errors:
3413 results.append(output_api.PresubmitError(
3414 'Annotations in android.test.suitebuilder.annotation have been'
3415 ' deprecated since API level 24. Please use android.support.test.filters'
3416 ' from //third_party/android_support_test_runner:runner_java instead.'
3417 ' Contact [email protected] if you have any questions.', errors))
3418 return results
3419
3420
agrieve7b6479d82015-10-07 14:24:223421def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3422 """Checks if MDPI assets are placed in a correct directory."""
3423 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3424 ('/res/drawable/' in f.LocalPath() or
3425 '/res/drawable-ldrtl/' in f.LocalPath()))
3426 errors = []
3427 for f in input_api.AffectedFiles(include_deletes=False,
3428 file_filter=file_filter):
3429 errors.append(' %s' % f.LocalPath())
3430
3431 results = []
3432 if errors:
3433 results.append(output_api.PresubmitError(
3434 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3435 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3436 '/res/drawable-ldrtl/.\n'
3437 'Contact [email protected] if you have questions.', errors))
3438 return results
3439
3440
Nate Fischer535972b2017-09-16 01:06:183441def _CheckAndroidWebkitImports(input_api, output_api):
3442 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353443 android.webview.ValueCallback except in the WebView glue layer
3444 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183445 """
3446 valuecallback_import_pattern = input_api.re.compile(
3447 r'^import android\.webkit\.ValueCallback;$')
3448
3449 errors = []
3450
3451 sources = lambda affected_file: input_api.FilterSourceFile(
3452 affected_file,
3453 black_list=(_EXCLUDED_PATHS +
3454 _TEST_CODE_EXCLUDED_PATHS +
3455 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353456 (r'^android_webview[\\/]glue[\\/].*',
3457 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493458 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183459
3460 for f in input_api.AffectedSourceFiles(sources):
3461 for line_num, line in f.ChangedContents():
3462 if valuecallback_import_pattern.search(line):
3463 errors.append("%s:%d" % (f.LocalPath(), line_num))
3464
3465 results = []
3466
3467 if errors:
3468 results.append(output_api.PresubmitError(
3469 'android.webkit.ValueCallback usage is detected outside of the glue'
3470 ' layer. To stay compatible with the support library, android.webkit.*'
3471 ' classes should only be used inside the glue layer and'
3472 ' org.chromium.base.Callback should be used instead.',
3473 errors))
3474
3475 return results
3476
3477
Becky Zhou7c69b50992018-12-10 19:37:573478def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3479 """Checks Android XML styles """
3480 import sys
3481 original_sys_path = sys.path
3482 try:
3483 sys.path = sys.path + [input_api.os_path.join(
3484 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3485 import checkxmlstyle
3486 finally:
3487 # Restore sys.path to what it was before.
3488 sys.path = original_sys_path
3489
3490 if is_check_on_upload:
3491 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3492 else:
3493 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3494
3495
agrievef32bcc72016-04-04 14:57:403496class PydepsChecker(object):
3497 def __init__(self, input_api, pydeps_files):
3498 self._file_cache = {}
3499 self._input_api = input_api
3500 self._pydeps_files = pydeps_files
3501
3502 def _LoadFile(self, path):
3503 """Returns the list of paths within a .pydeps file relative to //."""
3504 if path not in self._file_cache:
3505 with open(path) as f:
3506 self._file_cache[path] = f.read()
3507 return self._file_cache[path]
3508
3509 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3510 """Returns an interable of paths within the .pydep, relativized to //."""
3511 os_path = self._input_api.os_path
3512 pydeps_dir = os_path.dirname(pydeps_path)
3513 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3514 if not l.startswith('*'))
3515 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3516
3517 def _CreateFilesToPydepsMap(self):
3518 """Returns a map of local_path -> list_of_pydeps."""
3519 ret = {}
3520 for pydep_local_path in self._pydeps_files:
3521 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3522 ret.setdefault(path, []).append(pydep_local_path)
3523 return ret
3524
3525 def ComputeAffectedPydeps(self):
3526 """Returns an iterable of .pydeps files that might need regenerating."""
3527 affected_pydeps = set()
3528 file_to_pydeps_map = None
3529 for f in self._input_api.AffectedFiles(include_deletes=True):
3530 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463531 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3532 # subrepositories. We can't figure out which files change, so re-check
3533 # all files.
3534 # Changes to print_python_deps.py affect all .pydeps.
3535 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403536 return self._pydeps_files
3537 elif local_path.endswith('.pydeps'):
3538 if local_path in self._pydeps_files:
3539 affected_pydeps.add(local_path)
3540 elif local_path.endswith('.py'):
3541 if file_to_pydeps_map is None:
3542 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3543 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3544 return affected_pydeps
3545
3546 def DetermineIfStale(self, pydeps_path):
3547 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413548 import difflib
John Budorick47ca3fe2018-02-10 00:53:103549 import os
3550
agrievef32bcc72016-04-04 14:57:403551 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3552 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103553 env = dict(os.environ)
3554 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403555 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103556 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413557 old_contents = old_pydeps_data[2:]
3558 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403559 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413560 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403561
3562
Tibor Goldschwendt360793f72019-06-25 18:23:493563def _ParseGclientArgs():
3564 args = {}
3565 with open('build/config/gclient_args.gni', 'r') as f:
3566 for line in f:
3567 line = line.strip()
3568 if not line or line.startswith('#'):
3569 continue
3570 attribute, value = line.split('=')
3571 args[attribute.strip()] = value.strip()
3572 return args
3573
3574
agrievef32bcc72016-04-04 14:57:403575def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3576 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403577 # This check is for Python dependency lists (.pydeps files), and involves
3578 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3579 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283580 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003581 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493582 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403583 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3584 results = []
3585 # First, check for new / deleted .pydeps.
3586 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033587 # Check whether we are running the presubmit check for a file in src.
3588 # f.LocalPath is relative to repo (src, or internal repo).
3589 # os_path.exists is relative to src repo.
3590 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3591 # to src and we can conclude that the pydeps is in src.
3592 if input_api.os_path.exists(f.LocalPath()):
3593 if f.LocalPath().endswith('.pydeps'):
3594 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3595 results.append(output_api.PresubmitError(
3596 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3597 'remove %s' % f.LocalPath()))
3598 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3599 results.append(output_api.PresubmitError(
3600 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3601 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403602
3603 if results:
3604 return results
3605
3606 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3607
3608 for pydep_path in checker.ComputeAffectedPydeps():
3609 try:
phajdan.jr0d9878552016-11-04 10:49:413610 result = checker.DetermineIfStale(pydep_path)
3611 if result:
3612 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403613 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413614 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3615 'To regenerate, run:\n\n %s' %
3616 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403617 except input_api.subprocess.CalledProcessError as error:
3618 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3619 long_text=error.output)]
3620
3621 return results
3622
3623
glidere61efad2015-02-18 17:39:433624def _CheckSingletonInHeaders(input_api, output_api):
3625 """Checks to make sure no header files have |Singleton<|."""
3626 def FileFilter(affected_file):
3627 # It's ok for base/memory/singleton.h to have |Singleton<|.
3628 black_list = (_EXCLUDED_PATHS +
3629 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043630 (r"^base[\\/]memory[\\/]singleton\.h$",
3631 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473632 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433633 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3634
sergeyu34d21222015-09-16 00:11:443635 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433636 files = []
3637 for f in input_api.AffectedSourceFiles(FileFilter):
3638 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3639 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3640 contents = input_api.ReadFile(f)
3641 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243642 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433643 pattern.search(line)):
3644 files.append(f)
3645 break
3646
3647 if files:
yolandyandaabc6d2016-04-18 18:29:393648 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443649 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433650 'Please move them to an appropriate source file so that the ' +
3651 'template gets instantiated in a single compilation unit.',
3652 files) ]
3653 return []
3654
3655
[email protected]fd20b902014-05-09 02:14:533656_DEPRECATED_CSS = [
3657 # Values
3658 ( "-webkit-box", "flex" ),
3659 ( "-webkit-inline-box", "inline-flex" ),
3660 ( "-webkit-flex", "flex" ),
3661 ( "-webkit-inline-flex", "inline-flex" ),
3662 ( "-webkit-min-content", "min-content" ),
3663 ( "-webkit-max-content", "max-content" ),
3664
3665 # Properties
3666 ( "-webkit-background-clip", "background-clip" ),
3667 ( "-webkit-background-origin", "background-origin" ),
3668 ( "-webkit-background-size", "background-size" ),
3669 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443670 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533671
3672 # Functions
3673 ( "-webkit-gradient", "gradient" ),
3674 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3675 ( "-webkit-linear-gradient", "linear-gradient" ),
3676 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3677 ( "-webkit-radial-gradient", "radial-gradient" ),
3678 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3679]
3680
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203681
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493682# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243683def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533684 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253685 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343686 documentation and iOS CSS for dom distiller
3687 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253688 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533689 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493690 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253691 black_list = (_EXCLUDED_PATHS +
3692 _TEST_CODE_EXCLUDED_PATHS +
3693 input_api.DEFAULT_BLACK_LIST +
3694 (r"^chrome/common/extensions/docs",
3695 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343696 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443697 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253698 r"^native_client_sdk"))
3699 file_filter = lambda f: input_api.FilterSourceFile(
3700 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533701 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3702 for line_num, line in fpath.ChangedContents():
3703 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023704 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533705 results.append(output_api.PresubmitError(
3706 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3707 (fpath.LocalPath(), line_num, deprecated_value, value)))
3708 return results
3709
mohan.reddyf21db962014-10-16 12:26:473710
rlanday6802cf632017-05-30 17:48:363711def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363712 bad_files = {}
3713 for f in input_api.AffectedFiles(include_deletes=False):
3714 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493715 not f.LocalPath().startswith('third_party/blink') and
3716 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363717 continue
3718
Daniel Bratell65b033262019-04-23 08:17:063719 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363720 continue
3721
Vaclav Brozekd5de76a2018-03-17 07:57:503722 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363723 if "#include" in line and "../" in line]
3724 if not relative_includes:
3725 continue
3726 bad_files[f.LocalPath()] = relative_includes
3727
3728 if not bad_files:
3729 return []
3730
3731 error_descriptions = []
3732 for file_path, bad_lines in bad_files.iteritems():
3733 error_description = file_path
3734 for line in bad_lines:
3735 error_description += '\n ' + line
3736 error_descriptions.append(error_description)
3737
3738 results = []
3739 results.append(output_api.PresubmitError(
3740 'You added one or more relative #include paths (including "../").\n'
3741 'These shouldn\'t be used because they can be used to include headers\n'
3742 'from code that\'s not correctly specified as a dependency in the\n'
3743 'relevant BUILD.gn file(s).',
3744 error_descriptions))
3745
3746 return results
3747
Takeshi Yoshinoe387aa32017-08-02 13:16:133748
Daniel Bratell65b033262019-04-23 08:17:063749def _CheckForCcIncludes(input_api, output_api):
3750 """Check that nobody tries to include a cc file. It's a relatively
3751 common error which results in duplicate symbols in object
3752 files. This may not always break the build until someone later gets
3753 very confusing linking errors."""
3754 results = []
3755 for f in input_api.AffectedFiles(include_deletes=False):
3756 # We let third_party code do whatever it wants
3757 if (f.LocalPath().startswith('third_party') and
3758 not f.LocalPath().startswith('third_party/blink') and
3759 not f.LocalPath().startswith('third_party\\blink')):
3760 continue
3761
3762 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3763 continue
3764
3765 for _, line in f.ChangedContents():
3766 if line.startswith('#include "'):
3767 included_file = line.split('"')[1]
3768 if _IsCPlusPlusFile(input_api, included_file):
3769 # The most common naming for external files with C++ code,
3770 # apart from standard headers, is to call them foo.inc, but
3771 # Chromium sometimes uses foo-inc.cc so allow that as well.
3772 if not included_file.endswith(('.h', '-inc.cc')):
3773 results.append(output_api.PresubmitError(
3774 'Only header files or .inc files should be included in other\n'
3775 'C++ files. Compiling the contents of a cc file more than once\n'
3776 'will cause duplicate information in the build which may later\n'
3777 'result in strange link_errors.\n' +
3778 f.LocalPath() + ':\n ' +
3779 line))
3780
3781 return results
3782
3783
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203784def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3785 if not isinstance(key, ast.Str):
3786 return 'Key at line %d must be a string literal' % key.lineno
3787 if not isinstance(value, ast.Dict):
3788 return 'Value at line %d must be a dict' % value.lineno
3789 if len(value.keys) != 1:
3790 return 'Dict at line %d must have single entry' % value.lineno
3791 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3792 return (
3793 'Entry at line %d must have a string literal \'filepath\' as key' %
3794 value.lineno)
3795 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133796
Takeshi Yoshinoe387aa32017-08-02 13:16:133797
Sergey Ulanov4af16052018-11-08 02:41:463798def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203799 if not isinstance(key, ast.Str):
3800 return 'Key at line %d must be a string literal' % key.lineno
3801 if not isinstance(value, ast.List):
3802 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463803 for element in value.elts:
3804 if not isinstance(element, ast.Str):
3805 return 'Watchlist elements on line %d is not a string' % key.lineno
3806 if not email_regex.match(element.s):
3807 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3808 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203809 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133810
Takeshi Yoshinoe387aa32017-08-02 13:16:133811
Sergey Ulanov4af16052018-11-08 02:41:463812def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203813 mismatch_template = (
3814 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3815 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133816
Sergey Ulanov4af16052018-11-08 02:41:463817 email_regex = input_api.re.compile(
3818 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3819
3820 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203821 i = 0
3822 last_key = ''
3823 while True:
3824 if i >= len(wd_dict.keys):
3825 if i >= len(w_dict.keys):
3826 return None
3827 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3828 elif i >= len(w_dict.keys):
3829 return (
3830 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133831
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203832 wd_key = wd_dict.keys[i]
3833 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133834
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203835 result = _CheckWatchlistDefinitionsEntrySyntax(
3836 wd_key, wd_dict.values[i], ast)
3837 if result is not None:
3838 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133839
Sergey Ulanov4af16052018-11-08 02:41:463840 result = _CheckWatchlistsEntrySyntax(
3841 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203842 if result is not None:
3843 return 'Bad entry in WATCHLISTS dict: %s' % result
3844
3845 if wd_key.s != w_key.s:
3846 return mismatch_template % (
3847 '%s at line %d' % (wd_key.s, wd_key.lineno),
3848 '%s at line %d' % (w_key.s, w_key.lineno))
3849
3850 if wd_key.s < last_key:
3851 return (
3852 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3853 (wd_key.lineno, w_key.lineno))
3854 last_key = wd_key.s
3855
3856 i = i + 1
3857
3858
Sergey Ulanov4af16052018-11-08 02:41:463859def _CheckWATCHLISTSSyntax(expression, input_api):
3860 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203861 if not isinstance(expression, ast.Expression):
3862 return 'WATCHLISTS file must contain a valid expression'
3863 dictionary = expression.body
3864 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3865 return 'WATCHLISTS file must have single dict with exactly two entries'
3866
3867 first_key = dictionary.keys[0]
3868 first_value = dictionary.values[0]
3869 second_key = dictionary.keys[1]
3870 second_value = dictionary.values[1]
3871
3872 if (not isinstance(first_key, ast.Str) or
3873 first_key.s != 'WATCHLIST_DEFINITIONS' or
3874 not isinstance(first_value, ast.Dict)):
3875 return (
3876 'The first entry of the dict in WATCHLISTS file must be '
3877 'WATCHLIST_DEFINITIONS dict')
3878
3879 if (not isinstance(second_key, ast.Str) or
3880 second_key.s != 'WATCHLISTS' or
3881 not isinstance(second_value, ast.Dict)):
3882 return (
3883 'The second entry of the dict in WATCHLISTS file must be '
3884 'WATCHLISTS dict')
3885
Sergey Ulanov4af16052018-11-08 02:41:463886 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133887
3888
3889def _CheckWATCHLISTS(input_api, output_api):
3890 for f in input_api.AffectedFiles(include_deletes=False):
3891 if f.LocalPath() == 'WATCHLISTS':
3892 contents = input_api.ReadFile(f, 'r')
3893
3894 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203895 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133896 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203897 # Get an AST tree for it and scan the tree for detailed style checking.
3898 expression = input_api.ast.parse(
3899 contents, filename='WATCHLISTS', mode='eval')
3900 except ValueError as e:
3901 return [output_api.PresubmitError(
3902 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3903 except SyntaxError as e:
3904 return [output_api.PresubmitError(
3905 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3906 except TypeError as e:
3907 return [output_api.PresubmitError(
3908 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133909
Sergey Ulanov4af16052018-11-08 02:41:463910 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203911 if result is not None:
3912 return [output_api.PresubmitError(result)]
3913 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133914
3915 return []
3916
3917
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193918def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3919 """Checks that newly added header files have corresponding GN changes.
3920 Note that this is only a heuristic. To be precise, run script:
3921 build/check_gn_headers.py.
3922 """
3923
3924 def headers(f):
3925 return input_api.FilterSourceFile(
3926 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3927
3928 new_headers = []
3929 for f in input_api.AffectedSourceFiles(headers):
3930 if f.Action() != 'A':
3931 continue
3932 new_headers.append(f.LocalPath())
3933
3934 def gn_files(f):
3935 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3936
3937 all_gn_changed_contents = ''
3938 for f in input_api.AffectedSourceFiles(gn_files):
3939 for _, line in f.ChangedContents():
3940 all_gn_changed_contents += line
3941
3942 problems = []
3943 for header in new_headers:
3944 basename = input_api.os_path.basename(header)
3945 if basename not in all_gn_changed_contents:
3946 problems.append(header)
3947
3948 if problems:
3949 return [output_api.PresubmitPromptWarning(
3950 'Missing GN changes for new header files', items=sorted(problems),
3951 long_text='Please double check whether newly added header files need '
3952 'corresponding changes in gn or gni files.\nThis checking is only a '
3953 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3954 'Read https://crbug.com/661774 for more info.')]
3955 return []
3956
3957
Michael Giuffridad3bc8672018-10-25 22:48:023958def _CheckCorrectProductNameInMessages(input_api, output_api):
3959 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3960
3961 This assumes we won't intentionally reference one product from the other
3962 product.
3963 """
3964 all_problems = []
3965 test_cases = [{
3966 "filename_postfix": "google_chrome_strings.grd",
3967 "correct_name": "Chrome",
3968 "incorrect_name": "Chromium",
3969 }, {
3970 "filename_postfix": "chromium_strings.grd",
3971 "correct_name": "Chromium",
3972 "incorrect_name": "Chrome",
3973 }]
3974
3975 for test_case in test_cases:
3976 problems = []
3977 filename_filter = lambda x: x.LocalPath().endswith(
3978 test_case["filename_postfix"])
3979
3980 # Check each new line. Can yield false positives in multiline comments, but
3981 # easier than trying to parse the XML because messages can have nested
3982 # children, and associating message elements with affected lines is hard.
3983 for f in input_api.AffectedSourceFiles(filename_filter):
3984 for line_num, line in f.ChangedContents():
3985 if "<message" in line or "<!--" in line or "-->" in line:
3986 continue
3987 if test_case["incorrect_name"] in line:
3988 problems.append(
3989 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3990
3991 if problems:
3992 message = (
3993 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3994 % (test_case["correct_name"], test_case["correct_name"],
3995 test_case["incorrect_name"]))
3996 all_problems.append(
3997 output_api.PresubmitPromptWarning(message, items=problems))
3998
3999 return all_problems
4000
4001
Dirk Pranke3c18a382019-03-15 01:07:514002def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
4003 # TODO(crbug.com/941824): We need to make sure the entries in
4004 # //buildtools/DEPS are kept in sync with the entries in //DEPS
4005 # so that users of //buildtools in other projects get the same tooling
4006 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
4007 # support to gclient, we can eliminate the duplication and delete
4008 # this presubmit check.
4009
4010 # Update this regexp if new revisions are added to the files.
4011 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:014012 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:514013
4014 # If a user is changing one revision, they need to change the same
4015 # line in both files. This means that any given change should contain
4016 # exactly the same list of changed lines that match the regexps. The
4017 # replace(' ', '') call allows us to ignore whitespace changes to the
4018 # lines. The 'long_text' parameter to the error will contain the
4019 # list of changed lines in both files, which should make it easy enough
4020 # to spot the error without going overboard in this implementation.
4021 revs_changes = {
4022 'DEPS': {},
4023 'buildtools/DEPS': {},
4024 }
4025 long_text = ''
4026
4027 for f in input_api.AffectedFiles(
4028 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
4029 for line_num, line in f.ChangedContents():
4030 if rev_regexp.search(line):
4031 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
4032 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
4033
4034 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
4035 return [output_api.PresubmitError(
4036 'Change buildtools revisions in sync in both //DEPS and '
4037 '//buildtools/DEPS.', long_text=long_text + '\n')]
4038 else:
4039 return []
4040
4041
Daniel Bratell93eb6c62019-04-29 20:13:364042def _CheckForTooLargeFiles(input_api, output_api):
4043 """Avoid large files, especially binary files, in the repository since
4044 git doesn't scale well for those. They will be in everyone's repo
4045 clones forever, forever making Chromium slower to clone and work
4046 with."""
4047
4048 # Uploading files to cloud storage is not trivial so we don't want
4049 # to set the limit too low, but the upper limit for "normal" large
4050 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4051 # anything over 20 MB is exceptional.
4052 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4053
4054 too_large_files = []
4055 for f in input_api.AffectedFiles():
4056 # Check both added and modified files (but not deleted files).
4057 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384058 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364059 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4060 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4061
4062 if too_large_files:
4063 message = (
4064 'Do not commit large files to git since git scales badly for those.\n' +
4065 'Instead put the large files in cloud storage and use DEPS to\n' +
4066 'fetch them.\n' + '\n'.join(too_large_files)
4067 )
4068 return [output_api.PresubmitError(
4069 'Too large files found in commit', long_text=message + '\n')]
4070 else:
4071 return []
4072
Max Morozb47503b2019-08-08 21:03:274073
4074def _CheckFuzzTargets(input_api, output_api):
4075 """Checks specific for fuzz target sources."""
4076 EXPORTED_SYMBOLS = [
4077 'LLVMFuzzerInitialize',
4078 'LLVMFuzzerCustomMutator',
4079 'LLVMFuzzerCustomCrossOver',
4080 'LLVMFuzzerMutate',
4081 ]
4082
4083 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4084
4085 def FilterFile(affected_file):
4086 """Ignore libFuzzer source code."""
4087 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4088 black_list = r"^third_party[\\/]libFuzzer"
4089
4090 return input_api.FilterSourceFile(
4091 affected_file,
4092 white_list=[white_list],
4093 black_list=[black_list])
4094
4095 files_with_missing_header = []
4096 for f in input_api.AffectedSourceFiles(FilterFile):
4097 contents = input_api.ReadFile(f, 'r')
4098 if REQUIRED_HEADER in contents:
4099 continue
4100
4101 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4102 files_with_missing_header.append(f.LocalPath())
4103
4104 if not files_with_missing_header:
4105 return []
4106
4107 long_text = (
4108 'If you define any of the libFuzzer optional functions (%s), it is '
4109 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4110 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4111 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4112 'to access command line arguments passed to the fuzzer. Instead, prefer '
4113 'static initialization and shared resources as documented in '
4114 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4115 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4116 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4117 )
4118
4119 return [output_api.PresubmitPromptWarning(
4120 message="Missing '%s' in:" % REQUIRED_HEADER,
4121 items=files_with_missing_header,
4122 long_text=long_text)]
4123
4124
Mohamed Heikald048240a2019-11-12 16:57:374125def _CheckNewImagesWarning(input_api, output_api):
4126 """
4127 Warns authors who add images into the repo to make sure their images are
4128 optimized before committing.
4129 """
4130 images_added = False
4131 image_paths = []
4132 errors = []
4133 filter_lambda = lambda x: input_api.FilterSourceFile(
4134 x,
4135 black_list=(('(?i).*test', r'.*\/junit\/')
4136 + input_api.DEFAULT_BLACK_LIST),
4137 white_list=[r'.*\/(drawable|mipmap)' ]
4138 )
4139 for f in input_api.AffectedFiles(
4140 include_deletes=False, file_filter=filter_lambda):
4141 local_path = f.LocalPath().lower()
4142 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4143 images_added = True
4144 image_paths.append(f)
4145 if images_added:
4146 errors.append(output_api.PresubmitPromptWarning(
4147 'It looks like you are trying to commit some images. If these are '
4148 'non-test-only images, please make sure to read and apply the tips in '
4149 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4150 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4151 'FYI only and will not block your CL on the CQ.', image_paths))
4152 return errors
4153
4154
dgnaa68d5e2015-06-10 10:08:224155def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574156 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224157 results = []
dgnaa68d5e2015-06-10 10:08:224158 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174159 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224160 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294161 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064162 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4163 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424164 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184165 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574166 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374167 results.extend(_CheckNewImagesWarning(input_api, output_api))
Michael Thiessen44457642020-02-06 00:24:154168 results.extend(_CheckAndroidNoBannedImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574169 return results
4170
4171def _AndroidSpecificOnCommitChecks(input_api, output_api):
4172 """Groups commit checks that target android code."""
4173 results = []
4174 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224175 return results
4176
4177
[email protected]22c9bd72011-03-27 16:47:394178def _CommonChecks(input_api, output_api):
4179 """Checks common to both upload and commit."""
4180 results = []
4181 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384182 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544183 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084184
4185 author = input_api.change.author_email
4186 if author and author not in _KNOWN_ROBOTS:
4187 results.extend(
4188 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4189
[email protected]55459852011-08-10 15:17:194190 results.extend(
[email protected]760deea2013-12-10 19:33:494191 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234192 results.extend(
4193 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544194 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184195 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344196 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524197 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224198 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444199 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594200 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314201 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064202 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124203 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184204 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224205 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304206 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494207 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034208 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494209 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444210 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294211 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274212 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074213 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544214 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444215 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394216 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554217 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044218 results.extend(
4219 input_api.canned_checks.CheckChangeHasNoTabs(
4220 input_api,
4221 output_api,
4222 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404223 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164224 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084225 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244226 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474227 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044228 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054229 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144230 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234231 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434232 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404233 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154234 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174235 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264236 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504237 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364238 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064239 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134240 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434241 results.extend(input_api.RunTests(
4242 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144243 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024244 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514245 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364246 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004247 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244248
Vaclav Brozekcdc7defb2018-03-20 09:54:354249 for f in input_api.AffectedFiles():
4250 path, name = input_api.os_path.split(f.LocalPath())
4251 if name == 'PRESUBMIT.py':
4252 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004253 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4254 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074255 # The PRESUBMIT.py file (and the directory containing it) might
4256 # have been affected by being moved or removed, so only try to
4257 # run the tests if they still exist.
4258 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4259 input_api, output_api, full_path,
4260 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394261 return results
[email protected]1f7b4172010-01-28 01:17:344262
[email protected]b337cb5b2011-01-23 21:24:054263
[email protected]b8079ae4a2012-12-05 19:56:494264def _CheckPatchFiles(input_api, output_api):
4265 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4266 if f.LocalPath().endswith(('.orig', '.rej'))]
4267 if problems:
4268 return [output_api.PresubmitError(
4269 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034270 else:
4271 return []
[email protected]b8079ae4a2012-12-05 19:56:494272
4273
Kent Tamura5a8755d2017-06-29 23:37:074274def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214275 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4276 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4277 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074278 include_re = input_api.re.compile(
4279 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4280 extension_re = input_api.re.compile(r'\.[a-z]+$')
4281 errors = []
4282 for f in input_api.AffectedFiles():
4283 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4284 continue
4285 found_line_number = None
4286 found_macro = None
4287 for line_num, line in f.ChangedContents():
4288 match = macro_re.search(line)
4289 if match:
4290 found_line_number = line_num
4291 found_macro = match.group(2)
4292 break
4293 if not found_line_number:
4294 continue
4295
4296 found_include = False
4297 for line in f.NewContents():
4298 if include_re.search(line):
4299 found_include = True
4300 break
4301 if found_include:
4302 continue
4303
4304 if not f.LocalPath().endswith('.h'):
4305 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4306 try:
4307 content = input_api.ReadFile(primary_header_path, 'r')
4308 if include_re.search(content):
4309 continue
4310 except IOError:
4311 pass
4312 errors.append('%s:%d %s macro is used without including build/'
4313 'build_config.h.'
4314 % (f.LocalPath(), found_line_number, found_macro))
4315 if errors:
4316 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4317 return []
4318
4319
[email protected]b00342e7f2013-03-26 16:21:544320def _DidYouMeanOSMacro(bad_macro):
4321 try:
4322 return {'A': 'OS_ANDROID',
4323 'B': 'OS_BSD',
4324 'C': 'OS_CHROMEOS',
4325 'F': 'OS_FREEBSD',
4326 'L': 'OS_LINUX',
4327 'M': 'OS_MACOSX',
4328 'N': 'OS_NACL',
4329 'O': 'OS_OPENBSD',
4330 'P': 'OS_POSIX',
4331 'S': 'OS_SOLARIS',
4332 'W': 'OS_WIN'}[bad_macro[3].upper()]
4333 except KeyError:
4334 return ''
4335
4336
4337def _CheckForInvalidOSMacrosInFile(input_api, f):
4338 """Check for sensible looking, totally invalid OS macros."""
4339 preprocessor_statement = input_api.re.compile(r'^\s*#')
4340 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4341 results = []
4342 for lnum, line in f.ChangedContents():
4343 if preprocessor_statement.search(line):
4344 for match in os_macro.finditer(line):
4345 if not match.group(1) in _VALID_OS_MACROS:
4346 good = _DidYouMeanOSMacro(match.group(1))
4347 did_you_mean = ' (did you mean %s?)' % good if good else ''
4348 results.append(' %s:%d %s%s' % (f.LocalPath(),
4349 lnum,
4350 match.group(1),
4351 did_you_mean))
4352 return results
4353
4354
4355def _CheckForInvalidOSMacros(input_api, output_api):
4356 """Check all affected files for invalid OS macros."""
4357 bad_macros = []
tzik3f295992018-12-04 20:32:234358 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474359 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544360 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4361
4362 if not bad_macros:
4363 return []
4364
4365 return [output_api.PresubmitError(
4366 'Possibly invalid OS macro[s] found. Please fix your code\n'
4367 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4368
lliabraa35bab3932014-10-01 12:16:444369
4370def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4371 """Check all affected files for invalid "if defined" macros."""
4372 ALWAYS_DEFINED_MACROS = (
4373 "TARGET_CPU_PPC",
4374 "TARGET_CPU_PPC64",
4375 "TARGET_CPU_68K",
4376 "TARGET_CPU_X86",
4377 "TARGET_CPU_ARM",
4378 "TARGET_CPU_MIPS",
4379 "TARGET_CPU_SPARC",
4380 "TARGET_CPU_ALPHA",
4381 "TARGET_IPHONE_SIMULATOR",
4382 "TARGET_OS_EMBEDDED",
4383 "TARGET_OS_IPHONE",
4384 "TARGET_OS_MAC",
4385 "TARGET_OS_UNIX",
4386 "TARGET_OS_WIN32",
4387 )
4388 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4389 results = []
4390 for lnum, line in f.ChangedContents():
4391 for match in ifdef_macro.finditer(line):
4392 if match.group(1) in ALWAYS_DEFINED_MACROS:
4393 always_defined = ' %s is always defined. ' % match.group(1)
4394 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4395 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4396 lnum,
4397 always_defined,
4398 did_you_mean))
4399 return results
4400
4401
4402def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4403 """Check all affected files for invalid "if defined" macros."""
4404 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054405 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444406 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054407 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214408 continue
lliabraa35bab3932014-10-01 12:16:444409 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4410 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4411
4412 if not bad_macros:
4413 return []
4414
4415 return [output_api.PresubmitError(
4416 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4417 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4418 bad_macros)]
4419
4420
mlamouria82272622014-09-16 18:45:044421def _CheckForIPCRules(input_api, output_api):
4422 """Check for same IPC rules described in
4423 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4424 """
4425 base_pattern = r'IPC_ENUM_TRAITS\('
4426 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4427 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4428
4429 problems = []
4430 for f in input_api.AffectedSourceFiles(None):
4431 local_path = f.LocalPath()
4432 if not local_path.endswith('.h'):
4433 continue
4434 for line_number, line in f.ChangedContents():
4435 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4436 problems.append(
4437 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4438
4439 if problems:
4440 return [output_api.PresubmitPromptWarning(
4441 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4442 else:
4443 return []
4444
[email protected]b00342e7f2013-03-26 16:21:544445
Stephen Martinis97a394142018-06-07 23:06:054446def _CheckForLongPathnames(input_api, output_api):
4447 """Check to make sure no files being submitted have long paths.
4448 This causes issues on Windows.
4449 """
4450 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194451 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054452 local_path = f.LocalPath()
4453 # Windows has a path limit of 260 characters. Limit path length to 200 so
4454 # that we have some extra for the prefix on dev machines and the bots.
4455 if len(local_path) > 200:
4456 problems.append(local_path)
4457
4458 if problems:
4459 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4460 else:
4461 return []
4462
4463
Daniel Bratell8ba52722018-03-02 16:06:144464def _CheckForIncludeGuards(input_api, output_api):
4465 """Check that header files have proper guards against multiple inclusion.
4466 If a file should not have such guards (and it probably should) then it
4467 should include the string "no-include-guard-because-multiply-included".
4468 """
Daniel Bratell6a75baef62018-06-04 10:04:454469 def is_chromium_header_file(f):
4470 # We only check header files under the control of the Chromium
4471 # project. That is, those outside third_party apart from
4472 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324473 # We also exclude *_message_generator.h headers as they use
4474 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454475 file_with_path = input_api.os_path.normpath(f.LocalPath())
4476 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324477 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454478 (not file_with_path.startswith('third_party') or
4479 file_with_path.startswith(
4480 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144481
4482 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344483 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144484
4485 errors = []
4486
Daniel Bratell6a75baef62018-06-04 10:04:454487 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144488 guard_name = None
4489 guard_line_number = None
4490 seen_guard_end = False
4491
4492 file_with_path = input_api.os_path.normpath(f.LocalPath())
4493 base_file_name = input_api.os_path.splitext(
4494 input_api.os_path.basename(file_with_path))[0]
4495 upper_base_file_name = base_file_name.upper()
4496
4497 expected_guard = replace_special_with_underscore(
4498 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144499
4500 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574501 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4502 # are too many (1000+) files with slight deviations from the
4503 # coding style. The most important part is that the include guard
4504 # is there, and that it's unique, not the name so this check is
4505 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144506 #
4507 # As code becomes more uniform, this could be made stricter.
4508
4509 guard_name_pattern_list = [
4510 # Anything with the right suffix (maybe with an extra _).
4511 r'\w+_H__?',
4512
Daniel Bratell39b5b062018-05-16 18:09:574513 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144514 r'\w+_h',
4515
4516 # Anything including the uppercase name of the file.
4517 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4518 upper_base_file_name)) + r'\w*',
4519 ]
4520 guard_name_pattern = '|'.join(guard_name_pattern_list)
4521 guard_pattern = input_api.re.compile(
4522 r'#ifndef\s+(' + guard_name_pattern + ')')
4523
4524 for line_number, line in enumerate(f.NewContents()):
4525 if 'no-include-guard-because-multiply-included' in line:
4526 guard_name = 'DUMMY' # To not trigger check outside the loop.
4527 break
4528
4529 if guard_name is None:
4530 match = guard_pattern.match(line)
4531 if match:
4532 guard_name = match.group(1)
4533 guard_line_number = line_number
4534
Daniel Bratell39b5b062018-05-16 18:09:574535 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454536 # don't match the chromium style guide, but new files should
4537 # get it right.
4538 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574539 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144540 errors.append(output_api.PresubmitPromptWarning(
4541 'Header using the wrong include guard name %s' % guard_name,
4542 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574543 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144544 else:
4545 # The line after #ifndef should have a #define of the same name.
4546 if line_number == guard_line_number + 1:
4547 expected_line = '#define %s' % guard_name
4548 if line != expected_line:
4549 errors.append(output_api.PresubmitPromptWarning(
4550 'Missing "%s" for include guard' % expected_line,
4551 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4552 'Expected: %r\nGot: %r' % (expected_line, line)))
4553
4554 if not seen_guard_end and line == '#endif // %s' % guard_name:
4555 seen_guard_end = True
4556 elif seen_guard_end:
4557 if line.strip() != '':
4558 errors.append(output_api.PresubmitPromptWarning(
4559 'Include guard %s not covering the whole file' % (
4560 guard_name), [f.LocalPath()]))
4561 break # Nothing else to check and enough to warn once.
4562
4563 if guard_name is None:
4564 errors.append(output_api.PresubmitPromptWarning(
4565 'Missing include guard %s' % expected_guard,
4566 [f.LocalPath()],
4567 'Missing include guard in %s\n'
4568 'Recommended name: %s\n'
4569 'This check can be disabled by having the string\n'
4570 'no-include-guard-because-multiply-included in the header.' %
4571 (f.LocalPath(), expected_guard)))
4572
4573 return errors
4574
4575
mostynbb639aca52015-01-07 20:31:234576def _CheckForWindowsLineEndings(input_api, output_api):
4577 """Check source code and known ascii text files for Windows style line
4578 endings.
4579 """
earthdok1b5e0ee2015-03-10 15:19:104580 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234581
4582 file_inclusion_pattern = (
4583 known_text_files,
4584 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4585 )
4586
mostynbb639aca52015-01-07 20:31:234587 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534588 source_file_filter = lambda f: input_api.FilterSourceFile(
4589 f, white_list=file_inclusion_pattern, black_list=None)
4590 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504591 include_file = False
4592 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234593 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504594 include_file = True
4595 if include_file:
4596 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234597
4598 if problems:
4599 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4600 'these files to contain Windows style line endings?\n' +
4601 '\n'.join(problems))]
4602
4603 return []
4604
4605
Vaclav Brozekd5de76a2018-03-17 07:57:504606def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134607 """Checks that all source files use SYSLOG properly."""
4608 syslog_files = []
4609 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564610 for line_number, line in f.ChangedContents():
4611 if 'SYSLOG' in line:
4612 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4613
pastarmovj89f7ee12016-09-20 14:58:134614 if syslog_files:
4615 return [output_api.PresubmitPromptWarning(
4616 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4617 ' calls.\nFiles to check:\n', items=syslog_files)]
4618 return []
4619
4620
[email protected]1f7b4172010-01-28 01:17:344621def CheckChangeOnUpload(input_api, output_api):
4622 results = []
4623 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474624 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284625 results.extend(
jam93a6ee792017-02-08 23:59:224626 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194627 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224628 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134629 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164630 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534631 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194632 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274633 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544634 return results
[email protected]ca8d19842009-02-19 16:33:124635
4636
[email protected]1bfb8322014-04-23 01:02:414637def GetTryServerMasterForBot(bot):
4638 """Returns the Try Server master for the given bot.
4639
[email protected]0bb112362014-07-26 04:38:324640 It tries to guess the master from the bot name, but may still fail
4641 and return None. There is no longer a default master.
4642 """
4643 # Potentially ambiguous bot names are listed explicitly.
4644 master_map = {
tandriie5587792016-07-14 00:34:504645 'chromium_presubmit': 'master.tryserver.chromium.linux',
4646 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414647 }
[email protected]0bb112362014-07-26 04:38:324648 master = master_map.get(bot)
4649 if not master:
wnwen4fbaab82016-05-25 12:54:364650 if 'android' in bot:
tandriie5587792016-07-14 00:34:504651 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364652 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504653 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324654 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504655 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324656 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504657 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324658 return master
[email protected]1bfb8322014-04-23 01:02:414659
4660
[email protected]ca8d19842009-02-19 16:33:124661def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544662 results = []
[email protected]1f7b4172010-01-28 01:17:344663 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574664 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544665 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274666 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344667 input_api,
4668 output_api,
[email protected]2fdd1f362013-01-16 03:56:034669 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274670
jam93a6ee792017-02-08 23:59:224671 results.extend(
4672 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544673 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4674 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384675 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4676 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414677 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4678 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544679 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144680
4681
4682def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144683 import os
4684 import sys
4685 from io import StringIO
4686
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144687 new_or_added_paths = set(f.LocalPath()
4688 for f in input_api.AffectedFiles()
4689 if (f.Action() == 'A' or f.Action() == 'M'))
4690 removed_paths = set(f.LocalPath()
4691 for f in input_api.AffectedFiles(include_deletes=True)
4692 if f.Action() == 'D')
4693
4694 affected_grds = [f for f in input_api.AffectedFiles()
4695 if (f.LocalPath().endswith('.grd') or
4696 f.LocalPath().endswith('.grdp'))]
meacer8c0d3832019-12-26 21:46:164697 if not affected_grds:
4698 return []
4699
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144700 affected_png_paths = [f.AbsoluteLocalPath()
4701 for f in input_api.AffectedFiles()
4702 if (f.LocalPath().endswith('.png'))]
4703
4704 # Check for screenshots. Developers can upload screenshots using
4705 # tools/translation/upload_screenshots.py which finds and uploads
4706 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4707 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4708 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4709 #
4710 # The logic here is as follows:
4711 #
4712 # - If the CL has a .png file under the screenshots directory for a grd
4713 # file, warn the developer. Actual images should never be checked into the
4714 # Chrome repo.
4715 #
4716 # - If the CL contains modified or new messages in grd files and doesn't
4717 # contain the corresponding .sha1 files, warn the developer to add images
4718 # and upload them via tools/translation/upload_screenshots.py.
4719 #
4720 # - If the CL contains modified or new messages in grd files and the
4721 # corresponding .sha1 files, everything looks good.
4722 #
4723 # - If the CL contains removed messages in grd files but the corresponding
4724 # .sha1 files aren't removed, warn the developer to remove them.
4725 unnecessary_screenshots = []
4726 missing_sha1 = []
4727 unnecessary_sha1_files = []
4728
4729
4730 def _CheckScreenshotAdded(screenshots_dir, message_id):
4731 sha1_path = input_api.os_path.join(
4732 screenshots_dir, message_id + '.png.sha1')
4733 if sha1_path not in new_or_added_paths:
4734 missing_sha1.append(sha1_path)
4735
4736
4737 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4738 sha1_path = input_api.os_path.join(
4739 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034740 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144741 unnecessary_sha1_files.append(sha1_path)
4742
meacer8c0d3832019-12-26 21:46:164743 try:
4744 old_sys_path = sys.path
4745 sys.path = sys.path + [input_api.os_path.join(
4746 input_api.PresubmitLocalPath(), 'tools', 'translation')]
4747 from helper import grd_helper
4748 finally:
4749 sys.path = old_sys_path
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144750
4751 for f in affected_grds:
4752 file_path = f.LocalPath()
4753 old_id_to_msg_map = {}
4754 new_id_to_msg_map = {}
4755 if file_path.endswith('.grdp'):
4756 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584757 old_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394758 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144759 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584760 new_id_to_msg_map = grd_helper.GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394761 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144762 else:
meacerff8a9b62019-12-10 19:43:584763 file_dir = input_api.os_path.dirname(file_path) or '.'
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144764 if f.OldContents():
meacerff8a9b62019-12-10 19:43:584765 old_id_to_msg_map = grd_helper.GetGrdMessages(
4766 StringIO(unicode('\n'.join(f.OldContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144767 if f.NewContents():
meacerff8a9b62019-12-10 19:43:584768 new_id_to_msg_map = grd_helper.GetGrdMessages(
4769 StringIO(unicode('\n'.join(f.NewContents()))), file_dir)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144770
4771 # Compute added, removed and modified message IDs.
4772 old_ids = set(old_id_to_msg_map)
4773 new_ids = set(new_id_to_msg_map)
4774 added_ids = new_ids - old_ids
4775 removed_ids = old_ids - new_ids
4776 modified_ids = set([])
4777 for key in old_ids.intersection(new_ids):
4778 if (old_id_to_msg_map[key].FormatXml()
4779 != new_id_to_msg_map[key].FormatXml()):
4780 modified_ids.add(key)
4781
4782 grd_name, ext = input_api.os_path.splitext(
4783 input_api.os_path.basename(file_path))
4784 screenshots_dir = input_api.os_path.join(
4785 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4786
4787 # Check the screenshot directory for .png files. Warn if there is any.
4788 for png_path in affected_png_paths:
4789 if png_path.startswith(screenshots_dir):
4790 unnecessary_screenshots.append(png_path)
4791
4792 for added_id in added_ids:
4793 _CheckScreenshotAdded(screenshots_dir, added_id)
4794
4795 for modified_id in modified_ids:
4796 _CheckScreenshotAdded(screenshots_dir, modified_id)
4797
4798 for removed_id in removed_ids:
4799 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4800
4801 results = []
4802 if unnecessary_screenshots:
4803 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394804 'Do not include actual screenshots in the changelist. Run '
4805 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144806 sorted(unnecessary_screenshots)))
4807
4808 if missing_sha1:
4809 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394810 'You are adding or modifying UI strings.\n'
4811 'To ensure the best translations, take screenshots of the relevant UI '
4812 '(https://g.co/chrome/translation) and add these files to your '
4813 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144814
4815 if unnecessary_sha1_files:
4816 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394817 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144818 sorted(unnecessary_sha1_files)))
4819
4820 return results