blob: 6c86a695e152fc1e3f5a465091e1bd55ec7f83a1 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0413 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py",
14 r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py",
15 r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk",
16 r"^net[\\/]tools[\\/]spdyshark[\\/].*",
17 r"^skia[\\/].*",
Kent Tamura32dbbcb2018-11-30 12:28:4918 r"^third_party[\\/]blink[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0419 r"^third_party[\\/]breakpad[\\/].*",
Darwin Huangd74a9d32019-07-17 17:58:4620 # sqlite is an imported third party dependency.
21 r"^third_party[\\/]sqlite[\\/].*",
Egor Paskoce145c42018-09-28 19:31:0422 r"^v8[\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5324 r".+_autogen\.h$",
John Budorick1e701d322019-09-11 23:35:1225 r".+_pb2\.py$",
Egor Paskoce145c42018-09-28 19:31:0426 r".+[\\/]pnacl_shim\.c$",
27 r"^gpu[\\/]config[\\/].*_list_json\.cc$",
28 r"^chrome[\\/]browser[\\/]resources[\\/]pdf[\\/]index.js",
29 r"tools[\\/]md_browser[\\/].*\.css$",
Kenneth Russell077c8d92017-12-16 02:52:1430 # Test pages for Maps telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0431 r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*",
ehmaldonado78eee2ed2017-03-28 13:16:5432 # Test pages for WebRTC telemetry tests.
Egor Paskoce145c42018-09-28 19:31:0433 r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*",
[email protected]4306417642009-06-11 00:33:4034)
[email protected]ca8d1982009-02-19 16:33:1235
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Fragment of a regular expression that matches C++ and Objective-C++
38# implementation files.
39_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
40
wnwenbdc444e2016-05-25 13:44:1541
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:1942# Fragment of a regular expression that matches C++ and Objective-C++
43# header files.
44_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
45
46
[email protected]06e6d0ff2012-12-11 01:36:4447# Regular expression that matches code only used for test binaries
48# (best effort).
49_TEST_CODE_EXCLUDED_PATHS = (
Egor Paskoce145c42018-09-28 19:31:0450 r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Steven Holte27008b7422018-01-29 20:55:4452 r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1253 _IMPLEMENTATION_EXTENSIONS,
Matthew Denton63ea1e62019-03-25 20:39:1854 r'.+_(fuzz|fuzzer)(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4455 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
Egor Paskoce145c42018-09-28 19:31:0456 r'.*[\\/](test|tool(s)?)[\\/].*',
[email protected]ef070cc2013-05-03 11:53:0557 # content_shell is used for running layout tests.
Egor Paskoce145c42018-09-28 19:31:0458 r'content[\\/]shell[\\/].*',
[email protected]7b054982013-11-27 00:44:4759 # Non-production example code.
Egor Paskoce145c42018-09-28 19:31:0460 r'mojo[\\/]examples[\\/].*',
[email protected]8176de12014-06-20 19:07:0861 # Launcher for running iOS tests on the simulator.
Egor Paskoce145c42018-09-28 19:31:0462 r'testing[\\/]iossim[\\/]iossim\.mm$',
Olivier Robinbcea0fa2019-11-12 08:56:4163 # EarlGrey app side code for tests.
64 r'ios[\\/].*_app_interface\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4465)
[email protected]ca8d1982009-02-19 16:33:1266
Daniel Bratell609102be2019-03-27 20:53:2167_THIRD_PARTY_EXCEPT_BLINK = 'third_party/(?!blink/)'
wnwenbdc444e2016-05-25 13:44:1568
[email protected]eea609a2011-11-18 13:10:1269_TEST_ONLY_WARNING = (
70 'You might be calling functions intended only for testing from\n'
71 'production code. It is OK to ignore this warning if you know what\n'
72 'you are doing, as the heuristics used to detect the situation are\n'
Mohamed Heikal5cf63162019-10-25 19:59:0773 'not perfect. The commit queue will not block on this warning,\n'
74 'however the android-binary-size trybot will block if the method\n'
75 'exists in the release apk.')
[email protected]eea609a2011-11-18 13:10:1276
77
[email protected]cf9b78f2012-11-14 11:40:2878_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4079 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2180 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
81 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2882
wnwenbdc444e2016-05-25 13:44:1583
Daniel Bratell609102be2019-03-27 20:53:2184# Format: Sequence of tuples containing:
85# * String pattern or, if starting with a slash, a regular expression.
86# * Sequence of strings to show when the pattern matches.
87# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Eric Stevensona9a980972017-09-23 00:04:4188_BANNED_JAVA_FUNCTIONS = (
89 (
90 'StrictMode.allowThreadDiskReads()',
91 (
92 'Prefer using StrictModeContext.allowDiskReads() to using StrictMode '
93 'directly.',
94 ),
95 False,
96 ),
97 (
98 'StrictMode.allowThreadDiskWrites()',
99 (
100 'Prefer using StrictModeContext.allowDiskWrites() to using StrictMode '
101 'directly.',
102 ),
103 False,
104 ),
105)
106
Daniel Bratell609102be2019-03-27 20:53:21107# Format: Sequence of tuples containing:
108# * String pattern or, if starting with a slash, a regular expression.
109# * Sequence of strings to show when the pattern matches.
110# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
[email protected]127f18ec2012-06-16 05:05:59111_BANNED_OBJC_FUNCTIONS = (
112 (
113 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:59116 'prohibited. Please use CrTrackingArea instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 False,
120 ),
121 (
[email protected]eaae1972014-04-16 04:17:26122 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:59125 'instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 False,
129 ),
130 (
131 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertPoint:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertPoint:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
148 (
149 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20150 (
151 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59152 'Please use |convertRect:(point) fromView:nil| instead.',
153 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
154 ),
155 True,
156 ),
157 (
158 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20159 (
160 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59161 'Please use |convertRect:(point) toView:nil| instead.',
162 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
163 ),
164 True,
165 ),
166 (
167 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20168 (
169 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59170 'Please use |convertSize:(point) fromView:nil| instead.',
171 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
172 ),
173 True,
174 ),
175 (
176 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20177 (
178 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59179 'Please use |convertSize:(point) toView:nil| instead.',
180 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
181 ),
182 True,
183 ),
jif65398702016-10-27 10:19:48184 (
185 r"/\s+UTF8String\s*]",
186 (
187 'The use of -[NSString UTF8String] is dangerous as it can return null',
188 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
189 'Please use |SysNSStringToUTF8| instead.',
190 ),
191 True,
192 ),
Sylvain Defresne4cf1d182017-09-18 14:16:34193 (
194 r'__unsafe_unretained',
195 (
196 'The use of __unsafe_unretained is almost certainly wrong, unless',
197 'when interacting with NSFastEnumeration or NSInvocation.',
198 'Please use __weak in files build with ARC, nothing otherwise.',
199 ),
200 False,
201 ),
Avi Drissman7382afa02019-04-29 23:27:13202 (
203 'freeWhenDone:NO',
204 (
205 'The use of "freeWhenDone:NO" with the NoCopy creation of ',
206 'Foundation types is prohibited.',
207 ),
208 True,
209 ),
[email protected]127f18ec2012-06-16 05:05:59210)
211
Daniel Bratell609102be2019-03-27 20:53:21212# Format: Sequence of tuples containing:
213# * String pattern or, if starting with a slash, a regular expression.
214# * Sequence of strings to show when the pattern matches.
215# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
Sylvain Defresnea8b73d252018-02-28 15:45:54216_BANNED_IOS_OBJC_FUNCTIONS = (
217 (
218 r'/\bTEST[(]',
219 (
220 'TEST() macro should not be used in Objective-C++ code as it does not ',
221 'drain the autorelease pool at the end of the test. Use TEST_F() ',
222 'macro instead with a fixture inheriting from PlatformTest (or a ',
223 'typedef).'
224 ),
225 True,
226 ),
227 (
228 r'/\btesting::Test\b',
229 (
230 'testing::Test should not be used in Objective-C++ code as it does ',
231 'not drain the autorelease pool at the end of the test. Use ',
232 'PlatformTest instead.'
233 ),
234 True,
235 ),
236)
237
Peter K. Lee6c03ccff2019-07-15 14:40:05238# Format: Sequence of tuples containing:
239# * String pattern or, if starting with a slash, a regular expression.
240# * Sequence of strings to show when the pattern matches.
241# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
242_BANNED_IOS_EGTEST_FUNCTIONS = (
243 (
244 r'/\bEXPECT_OCMOCK_VERIFY\b',
245 (
246 'EXPECT_OCMOCK_VERIFY should not be used in EarlGrey tests because ',
247 'it is meant for GTests. Use [mock verify] instead.'
248 ),
249 True,
250 ),
251)
252
danakj7a2b7082019-05-21 21:13:51253# Directories that contain deprecated Bind() or Callback types.
254# Find sub-directories from a given directory by running:
danakjc8576092019-11-26 19:01:36255# for i in `find . -maxdepth 1 -type d|sort`; do
danakj7a2b7082019-05-21 21:13:51256# echo "-- $i"
danakj710b4c02019-11-28 16:08:45257# (cd $i; git grep -nP 'base::(Bind\(|(Callback<|Closure))'|wc -l)
danakj7a2b7082019-05-21 21:13:51258# done
259#
260# TODO(crbug.com/714018): Remove (or narrow the scope of) paths from this list
261# when they have been converted to modern callback types (OnceCallback,
262# RepeatingCallback, BindOnce, BindRepeating) in order to enable presubmit
263# checks for them and prevent regressions.
264_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK = '|'.join((
265 '^android_webview/browser/',
266 '^apps/',
267 '^ash/',
danakj7a2b7082019-05-21 21:13:51268 '^base/callback.h', # Intentional.
269 '^chrome/app/',
270 '^chrome/browser/',
271 '^chrome/chrome_elf/',
272 '^chrome/chrome_watcher/',
273 '^chrome/common/',
274 '^chrome/installer/',
danakj7a2b7082019-05-21 21:13:51275 '^chrome/renderer/',
276 '^chrome/services/',
277 '^chrome/test/',
278 '^chrome/tools/',
279 '^chrome/utility/',
280 '^chromecast/app/',
281 '^chromecast/browser/',
282 '^chromecast/crash/',
283 '^chromecast/media/',
284 '^chromecast/metrics/',
285 '^chromecast/net/',
286 '^chromeos/attestation/',
danakj7a2b7082019-05-21 21:13:51287 '^chromeos/components/',
danakj7a2b7082019-05-21 21:13:51288 '^chromeos/dbus/',
danakj7a2b7082019-05-21 21:13:51289 '^chromeos/login/',
290 '^chromeos/network/',
danakj7a2b7082019-05-21 21:13:51291 '^chromeos/services/',
292 '^chromeos/settings/',
danakj7a2b7082019-05-21 21:13:51293 '^components/arc/',
294 '^components/assist_ranker/',
295 '^components/autofill/',
296 '^components/autofill_assistant/',
297 '^components/bookmarks/',
danakj7a2b7082019-05-21 21:13:51298 '^components/browser_watcher/',
299 '^components/browsing_data/',
300 '^components/cast_channel/',
danakj7a2b7082019-05-21 21:13:51301 '^components/chromeos_camera/',
302 '^components/component_updater/',
303 '^components/content_settings/',
304 '^components/crash/',
305 '^components/cronet/',
306 '^components/data_reduction_proxy/',
307 '^components/discardable_memory/',
danakj7a2b7082019-05-21 21:13:51308 '^components/domain_reliability/',
danakjc8576092019-11-26 19:01:36309 '^components/dom_distiller/',
danakj7a2b7082019-05-21 21:13:51310 '^components/download/',
311 '^components/drive/',
312 '^components/exo/',
danakj7a2b7082019-05-21 21:13:51313 '^components/feature_engagement/',
314 '^components/feedback/',
315 '^components/flags_ui/',
316 '^components/gcm_driver/',
danakj7a2b7082019-05-21 21:13:51317 '^components/guest_view/',
318 '^components/heap_profiling/',
319 '^components/history/',
320 '^components/image_fetcher/',
321 '^components/invalidation/',
322 '^components/keyed_service/',
323 '^components/login/',
324 '^components/metrics/',
325 '^components/metrics_services_manager/',
326 '^components/nacl/',
327 '^components/navigation_interception/',
328 '^components/net_log/',
329 '^components/network_time/',
330 '^components/ntp_snippets/',
331 '^components/ntp_tiles/',
danakj7a2b7082019-05-21 21:13:51332 '^components/offline_pages/',
333 '^components/omnibox/',
334 '^components/ownership/',
danakj7a2b7082019-05-21 21:13:51335 '^components/password_manager/',
336 '^components/payments/',
337 '^components/plugins/',
338 '^components/policy/',
339 '^components/pref_registry/',
340 '^components/prefs/',
danakj7a2b7082019-05-21 21:13:51341 '^components/proxy_config/',
342 '^components/quirks/',
343 '^components/rappor/',
344 '^components/remote_cocoa/',
danakj7a2b7082019-05-21 21:13:51345 '^components/rlz/',
346 '^components/safe_browsing/',
347 '^components/search_engines/',
348 '^components/search_provider_logos/',
349 '^components/security_interstitials/',
350 '^components/security_state/',
351 '^components/services/',
352 '^components/sessions/',
353 '^components/signin/',
354 '^components/ssl_errors/',
355 '^components/storage_monitor/',
356 '^components/subresource_filter/',
357 '^components/suggestions/',
danakj7a2b7082019-05-21 21:13:51358 '^components/sync/',
danakj7a2b7082019-05-21 21:13:51359 '^components/sync_preferences/',
360 '^components/sync_sessions/',
361 '^components/test/',
362 '^components/tracing/',
363 '^components/translate/',
364 '^components/ukm/',
365 '^components/update_client/',
366 '^components/upload_list/',
367 '^components/variations/',
368 '^components/visitedlink/',
danakj7a2b7082019-05-21 21:13:51369 '^components/webcrypto/',
370 '^components/webdata/',
371 '^components/webdata_services/',
372 '^components/wifi/',
danakj7a2b7082019-05-21 21:13:51373 '^content/browser/',
danakj7a2b7082019-05-21 21:13:51374 '^content/public/',
danakj7a2b7082019-05-21 21:13:51375 '^device/bluetooth/',
danakj7a2b7082019-05-21 21:13:51376 '^extensions/',
danakj7a2b7082019-05-21 21:13:51377 '^google_apis/dive/',
378 '^google_apis/gaia/',
379 '^google_apis/gcm/',
380 '^headless/',
381 '^ios/chrome/',
382 '^ios/components/',
383 '^ios/net/',
384 '^ios/web/',
385 '^ios/web_view/',
386 '^ipc/',
danakj7a2b7082019-05-21 21:13:51387 '^media/audio/',
388 '^media/base/',
danakjc8576092019-11-26 19:01:36389 '^media/blink/',
danakj7a2b7082019-05-21 21:13:51390 '^media/capture/',
391 '^media/cast/',
392 '^media/cdm/',
393 '^media/device_monitors/',
394 '^media/ffmpeg/',
395 '^media/filters/',
396 '^media/formats/',
397 '^media/gpu/',
398 '^media/mojo/',
399 '^media/muxers/',
400 '^media/remoting/',
401 '^media/renderers/',
402 '^media/test/',
danakj7a2b7082019-05-21 21:13:51403 '^net/',
404 '^ppapi/proxy/',
405 '^ppapi/shared_impl/',
406 '^ppapi/tests/',
407 '^ppapi/thunk/',
408 '^remoting/base/',
409 '^remoting/client/',
410 '^remoting/codec/',
411 '^remoting/host/',
412 '^remoting/internal/',
413 '^remoting/ios/',
414 '^remoting/protocol/',
415 '^remoting/signaling/',
416 '^remoting/test/',
danakj7a2b7082019-05-21 21:13:51417 '^services/',
418 '^storage/browser/',
danakj7a2b7082019-05-21 21:13:51419 '^third_party/blink/',
420 '^third_party/crashpad/crashpad/test/gtest_main.cc',
421 '^third_party/leveldatabase/leveldb_chrome.cc',
422 '^third_party/boringssl/gtest_main_chromium.cc',
423 '^third_party/cacheinvalidation/overrides/' +
424 'google/cacheinvalidation/deps/callback.h',
425 '^third_party/libaddressinput/chromium/chrome_address_validator.cc',
426 '^third_party/zlib/google/',
427 '^tools/android/',
428 '^tools/clang/base_bind_rewriters/', # Intentional.
429 '^tools/gdb/gdb_chrome.py', # Intentional.
430 '^ui/accelerated_widget_mac/',
danakj7a2b7082019-05-21 21:13:51431 '^ui/base/',
432 '^ui/compositor/',
433 '^ui/display/',
danakjc8576092019-11-26 19:01:36434 '^weblayer/',
danakj7a2b7082019-05-21 21:13:51435))
[email protected]127f18ec2012-06-16 05:05:59436
Daniel Bratell609102be2019-03-27 20:53:21437# Format: Sequence of tuples containing:
438# * String pattern or, if starting with a slash, a regular expression.
439# * Sequence of strings to show when the pattern matches.
440# * Error flag. True if a match is a presubmit error, otherwise it's a warning.
441# * Sequence of paths to *not* check (regexps).
[email protected]127f18ec2012-06-16 05:05:59442_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20443 (
Dave Tapuska98199b612019-07-10 13:30:44444 r'/\bNULL\b',
thomasandersone7caaa9b2017-03-29 19:22:53445 (
446 'New code should not use NULL. Use nullptr instead.',
447 ),
Mohamed Amir Yosefea381072019-08-09 08:13:20448 False,
thomasandersone7caaa9b2017-03-29 19:22:53449 (),
450 ),
Peter Kasting94a56c42019-10-25 21:54:04451 (
452 r'/\busing namespace ',
453 (
454 'Using directives ("using namespace x") are banned by the Google Style',
455 'Guide ( http://google.github.io/styleguide/cppguide.html#Namespaces ).',
456 'Explicitly qualify symbols or use using declarations ("using x::foo").',
457 ),
458 True,
459 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
460 ),
Antonio Gomes07300d02019-03-13 20:59:57461 # Make sure that gtest's FRIEND_TEST() macro is not used; the
462 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
463 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
thomasandersone7caaa9b2017-03-29 19:22:53464 (
[email protected]23e6cbc2012-06-16 18:51:20465 'FRIEND_TEST(',
466 (
[email protected]e3c945502012-06-26 20:01:49467 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20468 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
469 ),
470 False,
[email protected]7345da02012-11-27 14:31:49471 (),
[email protected]23e6cbc2012-06-16 18:51:20472 ),
473 (
Dave Tapuska98199b612019-07-10 13:30:44474 r'/XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
thomasanderson4b569052016-09-14 20:15:53475 (
476 'Chrome clients wishing to select events on X windows should use',
477 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
478 'you are selecting events from the GPU process, or if you are using',
479 'an XDisplay other than gfx::GetXDisplay().',
480 ),
481 True,
482 (
Nick Diego Yamaneea6d999a2019-07-24 03:22:40483 r"^ui[\\/]events[\\/]x[\\/].*\.cc$",
Egor Paskoce145c42018-09-28 19:31:04484 r"^ui[\\/]gl[\\/].*\.cc$",
485 r"^media[\\/]gpu[\\/].*\.cc$",
486 r"^gpu[\\/].*\.cc$",
thomasanderson4b569052016-09-14 20:15:53487 ),
488 ),
489 (
Dave Tapuska98199b612019-07-10 13:30:44490 r'/XInternAtom|xcb_intern_atom',
thomasandersone043e3ce2017-06-08 00:43:20491 (
thomasanderson11aa41d2017-06-08 22:22:38492 'Use gfx::GetAtom() instead of interning atoms directly.',
thomasandersone043e3ce2017-06-08 00:43:20493 ),
494 True,
495 (
Egor Paskoce145c42018-09-28 19:31:04496 r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$",
497 r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$",
498 r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$",
thomasandersone043e3ce2017-06-08 00:43:20499 ),
500 ),
501 (
tomhudsone2c14d552016-05-26 17:07:46502 'setMatrixClip',
503 (
504 'Overriding setMatrixClip() is prohibited; ',
505 'the base function is deprecated. ',
506 ),
507 True,
508 (),
509 ),
510 (
[email protected]52657f62013-05-20 05:30:31511 'SkRefPtr',
512 (
513 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22514 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31515 ),
516 True,
517 (),
518 ),
519 (
520 'SkAutoRef',
521 (
522 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22523 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31524 ),
525 True,
526 (),
527 ),
528 (
529 'SkAutoTUnref',
530 (
531 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22532 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31533 ),
534 True,
535 (),
536 ),
537 (
538 'SkAutoUnref',
539 (
540 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
541 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22542 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31543 ),
544 True,
545 (),
546 ),
[email protected]d89eec82013-12-03 14:10:59547 (
548 r'/HANDLE_EINTR\(.*close',
549 (
550 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
551 'descriptor will be closed, and it is incorrect to retry the close.',
552 'Either call close directly and ignore its return value, or wrap close',
553 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
554 ),
555 True,
556 (),
557 ),
558 (
559 r'/IGNORE_EINTR\((?!.*close)',
560 (
561 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
562 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
563 ),
564 True,
565 (
566 # Files that #define IGNORE_EINTR.
Egor Paskoce145c42018-09-28 19:31:04567 r'^base[\\/]posix[\\/]eintr_wrapper\.h$',
568 r'^ppapi[\\/]tests[\\/]test_broker\.cc$',
[email protected]d89eec82013-12-03 14:10:59569 ),
570 ),
[email protected]ec5b3f02014-04-04 18:43:43571 (
572 r'/v8::Extension\(',
573 (
574 'Do not introduce new v8::Extensions into the code base, use',
575 'gin::Wrappable instead. See http://crbug.com/334679',
576 ),
577 True,
[email protected]f55c90ee62014-04-12 00:50:03578 (
Egor Paskoce145c42018-09-28 19:31:04579 r'extensions[\\/]renderer[\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03580 ),
[email protected]ec5b3f02014-04-04 18:43:43581 ),
skyostilf9469f72015-04-20 10:38:52582 (
jame2d1a952016-04-02 00:27:10583 '#pragma comment(lib,',
584 (
585 'Specify libraries to link with in build files and not in the source.',
586 ),
587 True,
Mirko Bonadeif4f0f0e2018-04-12 09:29:41588 (
tzik3f295992018-12-04 20:32:23589 r'^base[\\/]third_party[\\/]symbolize[\\/].*',
Egor Paskoce145c42018-09-28 19:31:04590 r'^third_party[\\/]abseil-cpp[\\/].*',
Mirko Bonadeif4f0f0e2018-04-12 09:29:41591 ),
jame2d1a952016-04-02 00:27:10592 ),
fdorayc4ac18d2017-05-01 21:39:59593 (
Gabriel Charette7cc6c432018-04-25 20:52:02594 r'/base::SequenceChecker\b',
gabd52c912a2017-05-11 04:15:59595 (
596 'Consider using SEQUENCE_CHECKER macros instead of the class directly.',
597 ),
598 False,
599 (),
600 ),
601 (
Gabriel Charette7cc6c432018-04-25 20:52:02602 r'/base::ThreadChecker\b',
gabd52c912a2017-05-11 04:15:59603 (
604 'Consider using THREAD_CHECKER macros instead of the class directly.',
605 ),
606 False,
607 (),
608 ),
dbeamb6f4fde2017-06-15 04:03:06609 (
Yuri Wiitala2f8de5c2017-07-21 00:11:06610 r'/(Time(|Delta|Ticks)|ThreadTicks)::FromInternalValue|ToInternalValue',
611 (
612 'base::TimeXXX::FromInternalValue() and ToInternalValue() are',
613 'deprecated (http://crbug.com/634507). Please avoid converting away',
614 'from the Time types in Chromium code, especially if any math is',
615 'being done on time values. For interfacing with platform/library',
616 'APIs, use FromMicroseconds() or InMicroseconds(), or one of the other',
617 'type converter methods instead. For faking TimeXXX values (for unit',
618 'testing only), use TimeXXX() + TimeDelta::FromMicroseconds(N). For',
619 'other use cases, please contact base/time/OWNERS.',
620 ),
621 False,
622 (),
623 ),
624 (
dbeamb6f4fde2017-06-15 04:03:06625 'CallJavascriptFunctionUnsafe',
626 (
627 "Don't use CallJavascriptFunctionUnsafe() in new code. Instead, use",
628 'AllowJavascript(), OnJavascriptAllowed()/OnJavascriptDisallowed(),',
629 'and CallJavascriptFunction(). See https://goo.gl/qivavq.',
630 ),
631 False,
632 (
Egor Paskoce145c42018-09-28 19:31:04633 r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$',
634 r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$',
635 r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$',
dbeamb6f4fde2017-06-15 04:03:06636 ),
637 ),
dskiba1474c2bfd62017-07-20 02:19:24638 (
639 'leveldb::DB::Open',
640 (
641 'Instead of leveldb::DB::Open() use leveldb_env::OpenDB() from',
642 'third_party/leveldatabase/env_chromium.h. It exposes databases to',
643 "Chrome's tracing, making their memory usage visible.",
644 ),
645 True,
646 (
647 r'^third_party/leveldatabase/.*\.(cc|h)$',
648 ),
Gabriel Charette0592c3a2017-07-26 12:02:04649 ),
650 (
Chris Mumfordc38afb62017-10-09 17:55:08651 'leveldb::NewMemEnv',
652 (
653 'Instead of leveldb::NewMemEnv() use leveldb_chrome::NewMemEnv() from',
Chris Mumford8d26d10a2018-04-20 17:07:58654 'third_party/leveldatabase/leveldb_chrome.h. It exposes environments',
655 "to Chrome's tracing, making their memory usage visible.",
Chris Mumfordc38afb62017-10-09 17:55:08656 ),
657 True,
658 (
659 r'^third_party/leveldatabase/.*\.(cc|h)$',
660 ),
661 ),
662 (
Gabriel Charetted9839bc2017-07-29 14:17:47663 'RunLoop::QuitCurrent',
664 (
Robert Liao64b7ab22017-08-04 23:03:43665 'Please migrate away from RunLoop::QuitCurrent*() methods. Use member',
666 'methods of a specific RunLoop instance instead.',
Gabriel Charetted9839bc2017-07-29 14:17:47667 ),
Gabriel Charettec0a8f3ee2018-04-25 20:49:41668 False,
Gabriel Charetted9839bc2017-07-29 14:17:47669 (),
Gabriel Charettea44975052017-08-21 23:14:04670 ),
671 (
672 'base::ScopedMockTimeMessageLoopTaskRunner',
673 (
Gabriel Charette87cc1af2018-04-25 20:52:51674 'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
Gabriel Charettedfa36042019-08-19 17:30:11675 'TaskEnvironment::TimeSource::MOCK_TIME. There are still a',
Gabriel Charette87cc1af2018-04-25 20:52:51676 'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
677 '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
678 'with gab@ first if you think you need it)',
Gabriel Charettea44975052017-08-21 23:14:04679 ),
Gabriel Charette87cc1af2018-04-25 20:52:51680 False,
Gabriel Charettea44975052017-08-21 23:14:04681 (),
Eric Stevenson6b47b44c2017-08-30 20:41:57682 ),
683 (
Dave Tapuska98199b612019-07-10 13:30:44684 'std::regex',
Eric Stevenson6b47b44c2017-08-30 20:41:57685 (
686 'Using std::regex adds unnecessary binary size to Chrome. Please use',
Mostyn Bramley-Moore6b427322017-12-21 22:11:02687 're2::RE2 instead (crbug.com/755321)',
Eric Stevenson6b47b44c2017-08-30 20:41:57688 ),
689 True,
690 (),
Francois Doray43670e32017-09-27 12:40:38691 ),
692 (
Peter Kasting991618a62019-06-17 22:00:09693 r'/\bstd::stoi\b',
694 (
695 'std::stoi uses exceptions to communicate results. ',
696 'Use base::StringToInt() instead.',
697 ),
698 True,
699 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
700 ),
701 (
702 r'/\bstd::stol\b',
703 (
704 'std::stol uses exceptions to communicate results. ',
705 'Use base::StringToInt() instead.',
706 ),
707 True,
708 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
709 ),
710 (
711 r'/\bstd::stoul\b',
712 (
713 'std::stoul uses exceptions to communicate results. ',
714 'Use base::StringToUint() instead.',
715 ),
716 True,
717 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
718 ),
719 (
720 r'/\bstd::stoll\b',
721 (
722 'std::stoll uses exceptions to communicate results. ',
723 'Use base::StringToInt64() instead.',
724 ),
725 True,
726 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
727 ),
728 (
729 r'/\bstd::stoull\b',
730 (
731 'std::stoull uses exceptions to communicate results. ',
732 'Use base::StringToUint64() instead.',
733 ),
734 True,
735 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
736 ),
737 (
738 r'/\bstd::stof\b',
739 (
740 'std::stof uses exceptions to communicate results. ',
741 'For locale-independent values, e.g. reading numbers from disk',
742 'profiles, use base::StringToDouble().',
743 'For user-visible values, parse using ICU.',
744 ),
745 True,
746 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
747 ),
748 (
749 r'/\bstd::stod\b',
750 (
751 'std::stod uses exceptions to communicate results. ',
752 'For locale-independent values, e.g. reading numbers from disk',
753 'profiles, use base::StringToDouble().',
754 'For user-visible values, parse using ICU.',
755 ),
756 True,
757 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
758 ),
759 (
760 r'/\bstd::stold\b',
761 (
762 'std::stold uses exceptions to communicate results. ',
763 'For locale-independent values, e.g. reading numbers from disk',
764 'profiles, use base::StringToDouble().',
765 'For user-visible values, parse using ICU.',
766 ),
767 True,
768 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
769 ),
770 (
Daniel Bratell69334cc2019-03-26 11:07:45771 r'/\bstd::to_string\b',
772 (
773 'std::to_string is locale dependent and slower than alternatives.',
Peter Kasting991618a62019-06-17 22:00:09774 'For locale-independent strings, e.g. writing numbers to disk',
775 'profiles, use base::NumberToString().',
Daniel Bratell69334cc2019-03-26 11:07:45776 'For user-visible strings, use base::FormatNumber() and',
777 'the related functions in base/i18n/number_formatting.h.',
778 ),
Peter Kasting991618a62019-06-17 22:00:09779 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21780 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45781 ),
782 (
783 r'/\bstd::shared_ptr\b',
784 (
785 'std::shared_ptr should not be used. Use scoped_refptr instead.',
786 ),
787 True,
Andreas Haas63f58792019-11-07 10:56:44788 [_THIRD_PARTY_EXCEPT_BLINK,
789 '^third_party/blink/renderer/core/typed_arrays/array_buffer/' +
790 'array_buffer_contents\.(cc|h)'],
Daniel Bratell609102be2019-03-27 20:53:21791 ),
792 (
Peter Kasting991618a62019-06-17 22:00:09793 r'/\bstd::weak_ptr\b',
794 (
795 'std::weak_ptr should not be used. Use base::WeakPtr instead.',
796 ),
797 True,
798 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
799 ),
800 (
Daniel Bratell609102be2019-03-27 20:53:21801 r'/\blong long\b',
802 (
803 'long long is banned. Use stdint.h if you need a 64 bit number.',
804 ),
805 False, # Only a warning since it is already used.
806 [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders.
807 ),
808 (
809 r'/\bstd::bind\b',
810 (
811 'std::bind is banned because of lifetime risks.',
812 'Use base::BindOnce or base::BindRepeating instead.',
813 ),
814 True,
815 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
816 ),
817 (
818 r'/\b#include <chrono>\b',
819 (
820 '<chrono> overlaps with Time APIs in base. Keep using',
821 'base classes.',
822 ),
823 True,
824 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
825 ),
826 (
827 r'/\b#include <exception>\b',
828 (
829 'Exceptions are banned and disabled in Chromium.',
830 ),
831 True,
832 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
833 ),
834 (
835 r'/\bstd::function\b',
836 (
837 'std::function is banned. Instead use base::Callback which directly',
838 'supports Chromium\'s weak pointers, ref counting and more.',
839 ),
Peter Kasting991618a62019-06-17 22:00:09840 False, # Only a warning since it is already used.
Daniel Bratell609102be2019-03-27 20:53:21841 [_THIRD_PARTY_EXCEPT_BLINK], # Do not warn in third_party folders.
842 ),
843 (
844 r'/\b#include <random>\b',
845 (
846 'Do not use any random number engines from <random>. Instead',
847 'use base::RandomBitGenerator.',
848 ),
849 True,
850 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
851 ),
852 (
853 r'/\bstd::ratio\b',
854 (
855 'std::ratio is banned by the Google Style Guide.',
856 ),
857 True,
858 [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders.
Daniel Bratell69334cc2019-03-26 11:07:45859 ),
860 (
Francois Doray43670e32017-09-27 12:40:38861 (r'/base::ThreadRestrictions::(ScopedAllowIO|AssertIOAllowed|'
862 r'DisallowWaiting|AssertWaitAllowed|SetWaitAllowed|ScopedAllowWait)'),
863 (
864 'Use the new API in base/threading/thread_restrictions.h.',
865 ),
Gabriel Charette04b138f2018-08-06 00:03:22866 False,
Francois Doray43670e32017-09-27 12:40:38867 (),
868 ),
Luis Hector Chavez9bbaed532017-11-30 18:25:38869 (
danakj7a2b7082019-05-21 21:13:51870 r'/\bbase::Bind\(',
871 (
872 'Please use base::Bind{Once,Repeating} instead',
873 'of base::Bind. (crbug.com/714018)',
874 ),
875 False,
Erik Staaba737d7602019-11-25 18:41:07876 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51877 ),
878 (
879 r'/\bbase::Callback[<:]',
880 (
881 'Please use base::{Once,Repeating}Callback instead',
882 'of base::Callback. (crbug.com/714018)',
883 ),
884 False,
Erik Staaba737d7602019-11-25 18:41:07885 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51886 ),
887 (
888 r'/\bbase::Closure\b',
889 (
890 'Please use base::{Once,Repeating}Closure instead',
891 'of base::Closure. (crbug.com/714018)',
892 ),
893 False,
Erik Staaba737d7602019-11-25 18:41:07894 (_NOT_CONVERTED_TO_MODERN_BIND_AND_CALLBACK,),
danakj7a2b7082019-05-21 21:13:51895 ),
896 (
Michael Giuffrida7f93d6922019-04-19 14:39:58897 r'/\bRunMessageLoop\b',
Gabriel Charette147335ea2018-03-22 15:59:19898 (
899 'RunMessageLoop is deprecated, use RunLoop instead.',
900 ),
901 False,
902 (),
903 ),
904 (
Dave Tapuska98199b612019-07-10 13:30:44905 'RunThisRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19906 (
907 'RunThisRunLoop is deprecated, use RunLoop directly instead.',
908 ),
909 False,
910 (),
911 ),
912 (
Dave Tapuska98199b612019-07-10 13:30:44913 'RunAllPendingInMessageLoop()',
Gabriel Charette147335ea2018-03-22 15:59:19914 (
915 "Prefer RunLoop over RunAllPendingInMessageLoop, please contact gab@",
916 "if you're convinced you need this.",
917 ),
918 False,
919 (),
920 ),
921 (
Dave Tapuska98199b612019-07-10 13:30:44922 'RunAllPendingInMessageLoop(BrowserThread',
Gabriel Charette147335ea2018-03-22 15:59:19923 (
924 'RunAllPendingInMessageLoop is deprecated. Use RunLoop for',
Gabriel Charette798fde72019-08-20 22:24:04925 'BrowserThread::UI, BrowserTaskEnvironment::RunIOThreadUntilIdle',
Gabriel Charette147335ea2018-03-22 15:59:19926 'for BrowserThread::IO, and prefer RunLoop::QuitClosure to observe',
927 'async events instead of flushing threads.',
928 ),
929 False,
930 (),
931 ),
932 (
933 r'MessageLoopRunner',
934 (
935 'MessageLoopRunner is deprecated, use RunLoop instead.',
936 ),
937 False,
938 (),
939 ),
940 (
Dave Tapuska98199b612019-07-10 13:30:44941 'GetDeferredQuitTaskForRunLoop',
Gabriel Charette147335ea2018-03-22 15:59:19942 (
943 "GetDeferredQuitTaskForRunLoop shouldn't be needed, please contact",
944 "gab@ if you found a use case where this is the only solution.",
945 ),
946 False,
947 (),
948 ),
949 (
Victor Costane48a2e82019-03-15 22:02:34950 'sqlite3_initialize(',
Victor Costan3653df62018-02-08 21:38:16951 (
Victor Costane48a2e82019-03-15 22:02:34952 'Instead of calling sqlite3_initialize(), depend on //sql, ',
Victor Costan3653df62018-02-08 21:38:16953 '#include "sql/initialize.h" and use sql::EnsureSqliteInitialized().',
954 ),
955 True,
956 (
957 r'^sql/initialization\.(cc|h)$',
958 r'^third_party/sqlite/.*\.(c|cc|h)$',
959 ),
960 ),
Matt Menke7f520a82018-03-28 21:38:37961 (
962 'net::URLFetcher',
963 (
964 'net::URLFetcher should no longer be used in content embedders. ',
965 'Instead, use network::SimpleURLLoader instead, which supports ',
966 'an out-of-process network stack. ',
967 'net::URLFetcher may still be used in binaries that do not embed',
968 'content.',
969 ),
Matt Menke59716d02018-04-05 12:45:53970 False,
Matt Menke7f520a82018-03-28 21:38:37971 (
Egor Paskoce145c42018-09-28 19:31:04972 r'^ios[\\/].*\.(cc|h)$',
973 r'.*[\\/]ios[\\/].*\.(cc|h)$',
Matt Menke7f520a82018-03-28 21:38:37974 r'.*_ios\.(cc|h)$',
Egor Paskoce145c42018-09-28 19:31:04975 r'^net[\\/].*\.(cc|h)$',
976 r'.*[\\/]tools[\\/].*\.(cc|h)$',
Fabrice de Gans-Riberi9345311c2019-08-30 23:33:43977 r'^fuchsia/base/test_devtools_list_fetcher\.cc$',
Matt Menke7f520a82018-03-28 21:38:37978 ),
979 ),
jdoerried7d10ab2018-04-27 10:46:13980 (
Dave Tapuska98199b612019-07-10 13:30:44981 'std::random_shuffle',
tzik5de2157f2018-05-08 03:42:47982 (
983 'std::random_shuffle is deprecated in C++14, and removed in C++17. Use',
984 'base::RandomShuffle instead.'
985 ),
986 True,
987 (),
988 ),
Javier Ernesto Flores Robles749e6c22018-10-08 09:36:24989 (
990 'ios/web/public/test/http_server',
991 (
992 'web::HTTPserver is deprecated use net::EmbeddedTestServer instead.',
993 ),
994 False,
995 (),
996 ),
Robert Liao764c9492019-01-24 18:46:28997 (
998 'GetAddressOf',
999 (
1000 'Improper use of Microsoft::WRL::ComPtr<T>::GetAddressOf() has been ',
Robert Liaoe794041e2019-10-03 17:16:461001 'implicated in a few leaks. Use operator& instead. See ',
1002 'http://crbug.com/914910 for more conversion guidance.'
Robert Liao764c9492019-01-24 18:46:281003 ),
1004 True,
1005 (),
1006 ),
Antonio Gomes07300d02019-03-13 20:59:571007 (
1008 'DEFINE_TYPE_CASTS',
1009 (
1010 'DEFINE_TYPE_CASTS is deprecated. Instead, use downcast helpers from ',
1011 '//third_party/blink/renderer/platform/casting.h.'
1012 ),
1013 True,
1014 (
1015 r'^third_party/blink/renderer/.*\.(cc|h)$',
1016 ),
1017 ),
Carlos Knippschildab192b8c2019-04-08 20:02:381018 (
Abhijeet Kandalkar1e7c2502019-10-29 15:05:451019 r'/\bIsHTML.+Element\(\b',
1020 (
1021 'Function IsHTMLXXXXElement is deprecated. Instead, use downcast ',
1022 ' helpers IsA<HTMLXXXXElement> from ',
1023 '//third_party/blink/renderer/platform/casting.h.'
1024 ),
1025 False,
1026 (
1027 r'^third_party/blink/renderer/.*\.(cc|h)$',
1028 ),
1029 ),
1030 (
1031 r'/\bToHTML.+Element(|OrNull)\(\b',
1032 (
1033 'Function ToHTMLXXXXElement and ToHTMLXXXXElementOrNull are '
1034 'deprecated. Instead, use downcast helpers To<HTMLXXXXElement> '
1035 'and DynamicTo<HTMLXXXXElement> from ',
1036 '//third_party/blink/renderer/platform/casting.h.'
1037 'auto* html_xxxx_ele = To<HTMLXXXXElement>(n)'
1038 'auto* html_xxxx_ele_or_null = DynamicTo<HTMLXXXXElement>(n)'
1039 ),
1040 False,
1041 (
1042 r'^third_party/blink/renderer/.*\.(cc|h)$',
1043 ),
1044 ),
1045 (
Kinuko Yasuda376c2ce12019-04-16 01:20:371046 r'/\bmojo::DataPipe\b',
Carlos Knippschildab192b8c2019-04-08 20:02:381047 (
1048 'mojo::DataPipe is deprecated. Use mojo::CreateDataPipe instead.',
1049 ),
1050 True,
1051 (),
1052 ),
Ben Lewisa9514602019-04-29 17:53:051053 (
1054 'SHFileOperation',
1055 (
1056 'SHFileOperation was deprecated in Windows Vista, and there are less ',
1057 'complex functions to achieve the same goals. Use IFileOperation for ',
1058 'any esoteric actions instead.'
1059 ),
1060 True,
1061 (),
1062 ),
Cliff Smolinskyb11abed2019-04-29 19:43:181063 (
Cliff Smolinsky81951642019-04-30 21:39:511064 'StringFromGUID2',
1065 (
1066 'StringFromGUID2 introduces an unnecessary dependency on ole32.dll.',
1067 'Use base::win::String16FromGUID instead.'
1068 ),
1069 True,
1070 (
1071 r'/base/win/win_util_unittest.cc'
1072 ),
1073 ),
1074 (
1075 'StringFromCLSID',
1076 (
1077 'StringFromCLSID introduces an unnecessary dependency on ole32.dll.',
1078 'Use base::win::String16FromGUID instead.'
1079 ),
1080 True,
1081 (
1082 r'/base/win/win_util_unittest.cc'
1083 ),
1084 ),
1085 (
Avi Drissman7382afa02019-04-29 23:27:131086 'kCFAllocatorNull',
1087 (
1088 'The use of kCFAllocatorNull with the NoCopy creation of ',
1089 'CoreFoundation types is prohibited.',
1090 ),
1091 True,
1092 (),
1093 ),
Oksana Zhuravlovafd247772019-05-16 16:57:291094 (
1095 'mojo::ConvertTo',
1096 (
1097 'mojo::ConvertTo and TypeConverter are deprecated. Please consider',
1098 'StructTraits / UnionTraits / EnumTraits / ArrayTraits / MapTraits /',
1099 'StringTraits if you would like to convert between custom types and',
1100 'the wire format of mojom types.'
1101 ),
Oksana Zhuravlova1d3b59de2019-05-17 00:08:221102 False,
Oksana Zhuravlovafd247772019-05-16 16:57:291103 (
Wezf89dec092019-09-11 19:38:331104 r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
1105 r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
Oksana Zhuravlovafd247772019-05-16 16:57:291106 r'^third_party/blink/.*\.(cc|h)$',
1107 r'^content/renderer/.*\.(cc|h)$',
1108 ),
1109 ),
Robert Liao1d78df52019-11-11 20:02:011110 (
1111 'CComPtr',
1112 (
1113 'New code should use Microsoft::WRL::ComPtr from wrl/client.h as a ',
1114 'replacement for CComPtr from ATL. See http://crbug.com/5027 for more ',
1115 'details.'
1116 ),
1117 False,
1118 (),
1119 ),
[email protected]127f18ec2012-06-16 05:05:591120)
1121
Mario Sanchez Prada2472cab2019-09-18 10:58:311122# Format: Sequence of tuples containing:
1123# * String pattern or, if starting with a slash, a regular expression.
1124# * Sequence of strings to show when the pattern matches.
1125_DEPRECATED_MOJO_TYPES = (
1126 (
1127 r'/\bmojo::AssociatedBinding\b',
1128 (
1129 'mojo::AssociatedBinding<Interface> is deprecated.',
1130 'Use mojo::AssociatedReceiver<Interface> instead.',
1131 ),
1132 ),
1133 (
1134 r'/\bmojo::AssociatedBindingSet\b',
1135 (
1136 'mojo::AssociatedBindingSet<Interface> is deprecated.',
1137 'Use mojo::AssociatedReceiverSet<Interface> instead.',
1138 ),
1139 ),
1140 (
1141 r'/\bmojo::AssociatedInterfacePtr\b',
1142 (
1143 'mojo::AssociatedInterfacePtr<Interface> is deprecated.',
1144 'Use mojo::AssociatedRemote<Interface> instead.',
1145 ),
1146 ),
1147 (
1148 r'/\bmojo::AssociatedInterfacePtrInfo\b',
1149 (
1150 'mojo::AssociatedInterfacePtrInfo<Interface> is deprecated.',
1151 'Use mojo::PendingAssociatedRemote<Interface> instead.',
1152 ),
1153 ),
1154 (
1155 r'/\bmojo::AssociatedInterfaceRequest\b',
1156 (
1157 'mojo::AssociatedInterfaceRequest<Interface> is deprecated.',
1158 'Use mojo::PendingAssociatedReceiver<Interface> instead.',
1159 ),
1160 ),
1161 (
1162 r'/\bmojo::Binding\b',
1163 (
1164 'mojo::Binding<Interface> is deprecated.',
1165 'Use mojo::Receiver<Interface> instead.',
1166 ),
1167 ),
1168 (
1169 r'/\bmojo::BindingSet\b',
1170 (
1171 'mojo::BindingSet<Interface> is deprecated.',
1172 'Use mojo::ReceiverSet<Interface> instead.',
1173 ),
1174 ),
1175 (
1176 r'/\bmojo::InterfacePtr\b',
1177 (
1178 'mojo::InterfacePtr<Interface> is deprecated.',
1179 'Use mojo::Remote<Interface> instead.',
1180 ),
1181 ),
1182 (
1183 r'/\bmojo::InterfacePtrInfo\b',
1184 (
1185 'mojo::InterfacePtrInfo<Interface> is deprecated.',
1186 'Use mojo::PendingRemote<Interface> instead.',
1187 ),
1188 ),
1189 (
1190 r'/\bmojo::InterfaceRequest\b',
1191 (
1192 'mojo::InterfaceRequest<Interface> is deprecated.',
1193 'Use mojo::PendingReceiver<Interface> instead.',
1194 ),
1195 ),
1196 (
1197 r'/\bmojo::MakeRequest\b',
1198 (
1199 'mojo::MakeRequest is deprecated.',
1200 'Use mojo::Remote::BindNewPipeAndPassReceiver() instead.',
1201 ),
1202 ),
1203 (
1204 r'/\bmojo::MakeRequestAssociatedWithDedicatedPipe\b',
1205 (
1206 'mojo::MakeRequest is deprecated.',
1207 'Use mojo::AssociatedRemote::'
1208 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.',
1209 ),
1210 ),
1211 (
1212 r'/\bmojo::MakeStrongBinding\b',
1213 (
1214 'mojo::MakeStrongBinding is deprecated.',
1215 'Either migrate to mojo::UniqueReceiverSet, if possible, or use',
1216 'mojo::MakeSelfOwnedReceiver() instead.',
1217 ),
1218 ),
1219 (
1220 r'/\bmojo::MakeStrongAssociatedBinding\b',
1221 (
1222 'mojo::MakeStrongAssociatedBinding is deprecated.',
1223 'Either migrate to mojo::UniqueAssociatedReceiverSet, if possible, or',
1224 'use mojo::MakeSelfOwnedAssociatedReceiver() instead.',
1225 ),
1226 ),
1227 (
1228 r'/\bmojo::StrongAssociatedBindingSet\b',
1229 (
1230 'mojo::StrongAssociatedBindingSet<Interface> is deprecated.',
1231 'Use mojo::UniqueAssociatedReceiverSet<Interface> instead.',
1232 ),
1233 ),
1234 (
1235 r'/\bmojo::StrongBindingSet\b',
1236 (
1237 'mojo::StrongBindingSet<Interface> is deprecated.',
1238 'Use mojo::UniqueReceiverSet<Interface> instead.',
1239 ),
1240 ),
1241)
wnwenbdc444e2016-05-25 13:44:151242
mlamouria82272622014-09-16 18:45:041243_IPC_ENUM_TRAITS_DEPRECATED = (
1244 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501245 'See http://www.chromium.org/Home/chromium-security/education/'
1246 'security-tips-for-ipc')
mlamouria82272622014-09-16 18:45:041247
Stephen Martinis97a394142018-06-07 23:06:051248_LONG_PATH_ERROR = (
1249 'Some files included in this CL have file names that are too long (> 200'
1250 ' characters). If committed, these files will cause issues on Windows. See'
1251 ' https://crbug.com/612667 for more details.'
1252)
1253
Shenghua Zhangbfaa38b82017-11-16 21:58:021254_JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [
Egor Paskoce145c42018-09-28 19:31:041255 r".*[\\/]BuildHooksAndroidImpl\.java",
1256 r".*[\\/]LicenseContentProvider\.java",
1257 r".*[\\/]PlatformServiceBridgeImpl.java",
Patrick Noland5475bc0d2018-10-01 20:04:281258 r".*chrome[\\\/]android[\\\/]feed[\\\/]dummy[\\\/].*\.java",
Shenghua Zhangbfaa38b82017-11-16 21:58:021259]
[email protected]127f18ec2012-06-16 05:05:591260
Mohamed Heikald048240a2019-11-12 16:57:371261# List of image extensions that are used as resources in chromium.
1262_IMAGE_EXTENSIONS = ['.svg', '.png', '.webp']
1263
Sean Kau46e29bc2017-08-28 16:31:161264# These paths contain test data and other known invalid JSON files.
1265_KNOWN_INVALID_JSON_FILE_PATTERNS = [
Egor Paskoce145c42018-09-28 19:31:041266 r'test[\\/]data[\\/]',
1267 r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$',
1268 r'^third_party[\\/]protobuf[\\/]',
Egor Paskoce145c42018-09-28 19:31:041269 r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$',
Kent Tamura77578cc2018-11-25 22:33:431270 r'^third_party[\\/]blink[\\/]web_tests[\\/]external[\\/]wpt[\\/]',
Sean Kau46e29bc2017-08-28 16:31:161271]
1272
1273
[email protected]b00342e7f2013-03-26 16:21:541274_VALID_OS_MACROS = (
1275 # Please keep sorted.
rayb0088ee52017-04-26 22:35:081276 'OS_AIX',
[email protected]b00342e7f2013-03-26 16:21:541277 'OS_ANDROID',
Henrique Nakashimaafff0502018-01-24 17:14:121278 'OS_ASMJS',
[email protected]b00342e7f2013-03-26 16:21:541279 'OS_BSD',
1280 'OS_CAT', # For testing.
1281 'OS_CHROMEOS',
Eugene Kliuchnikovb99125c2018-11-26 17:33:041282 'OS_CYGWIN', # third_party code.
[email protected]b00342e7f2013-03-26 16:21:541283 'OS_FREEBSD',
scottmg2f97ee122017-05-12 17:50:371284 'OS_FUCHSIA',
[email protected]b00342e7f2013-03-26 16:21:541285 'OS_IOS',
1286 'OS_LINUX',
1287 'OS_MACOSX',
1288 'OS_NACL',
hidehikof7295f22014-10-28 11:57:211289 'OS_NACL_NONSFI',
1290 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:121291 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:541292 'OS_OPENBSD',
1293 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:371294 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:541295 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:541296 'OS_WIN',
1297)
1298
1299
agrievef32bcc72016-04-04 14:57:401300_ANDROID_SPECIFIC_PYDEPS_FILES = [
Andrew Luob2e4b342018-09-20 19:32:391301 'android_webview/tools/run_cts.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361302 'base/android/jni_generator/jni_generator.pydeps',
1303 'base/android/jni_generator/jni_registration_generator.pydeps',
Egor Pasko56273b52019-03-14 14:45:221304 'build/android/devil_chromium.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361305 'build/android/gyp/aar.pydeps',
1306 'build/android/gyp/aidl.pydeps',
Tibor Goldschwendt0bef2d7a2019-10-24 21:19:271307 'build/android/gyp/allot_native_libraries.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361308 'build/android/gyp/apkbuilder.pydeps',
Andrew Grievea417ad302019-02-06 19:54:381309 'build/android/gyp/assert_static_initializers.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361310 'build/android/gyp/bytecode_processor.pydeps',
1311 'build/android/gyp/compile_resources.pydeps',
Tibor Goldschwendt84ec04c2019-08-23 21:19:091312 'build/android/gyp/create_app_bundle_apks.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361313 'build/android/gyp/create_bundle_wrapper_script.pydeps',
1314 'build/android/gyp/copy_ex.pydeps',
1315 'build/android/gyp/create_app_bundle.pydeps',
1316 'build/android/gyp/create_apk_operations_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361317 'build/android/gyp/create_java_binary_script.pydeps',
Andrew Grieveb838d832019-02-11 16:55:221318 'build/android/gyp/create_size_info_files.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361319 'build/android/gyp/desugar.pydeps',
Sam Maier3599daa2018-11-26 18:02:591320 'build/android/gyp/dexsplitter.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361321 'build/android/gyp/dex.pydeps',
1322 'build/android/gyp/dist_aar.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361323 'build/android/gyp/filter_zip.pydeps',
1324 'build/android/gyp/gcc_preprocess.pydeps',
Christopher Grant99e0e20062018-11-21 21:22:361325 'build/android/gyp/generate_linker_version_script.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361326 'build/android/gyp/ijar.pydeps',
Yun Liueb4075ddf2019-05-13 19:47:581327 'build/android/gyp/jacoco_instr.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361328 'build/android/gyp/java_cpp_enum.pydeps',
Ian Vollickb99472e2019-03-07 21:35:261329 'build/android/gyp/java_cpp_strings.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361330 'build/android/gyp/javac.pydeps',
1331 'build/android/gyp/jinja_template.pydeps',
1332 'build/android/gyp/lint.pydeps',
1333 'build/android/gyp/main_dex_list.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361334 'build/android/gyp/merge_manifest.pydeps',
1335 'build/android/gyp/prepare_resources.pydeps',
1336 'build/android/gyp/proguard.pydeps',
Eric Stevensona82cf6082019-07-24 14:35:241337 'build/android/gyp/validate_static_library_dex_references.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361338 'build/android/gyp/write_build_config.pydeps',
Tibor Goldschwendtc4caae92019-07-12 00:33:461339 'build/android/gyp/write_native_libraries_java.pydeps',
Andrew Grieve9ff17792018-11-30 04:55:561340 'build/android/gyp/zip.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361341 'build/android/incremental_install/generate_android_manifest.pydeps',
1342 'build/android/incremental_install/write_installer_json.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221343 'build/android/resource_sizes.pydeps',
agrievef32bcc72016-04-04 14:57:401344 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:041345 'build/android/test_wrapper/logdog_wrapper.pydeps',
David 'Digit' Turner0006f4732018-08-07 07:12:361346 'build/protoc_java.pydeps',
Peter Wene410bd792019-04-29 18:05:411347 'chrome/android/features/create_stripped_java_factory.pydeps',
Tibor Goldschwendtc748dfca42019-10-24 19:39:051348 'components/module_installer/android/module_desc_java.pydeps',
agrieve732db3a2016-04-26 19:18:191349 'net/tools/testserver/testserver.pydeps',
Andrew Luo338fe6e82019-09-19 07:17:431350 'testing/scripts/run_android_wpt.pydeps',
Peter Wen22bc3ec2019-03-28 22:18:021351 'third_party/android_platform/development/scripts/stack.pydeps',
agrievef32bcc72016-04-04 14:57:401352]
1353
wnwenbdc444e2016-05-25 13:44:151354
agrievef32bcc72016-04-04 14:57:401355_GENERIC_PYDEPS_FILES = [
anthonyvd7323c982019-09-11 14:36:421356 'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131357 'chrome/test/chromedriver/test/run_py_tests.pydeps',
Hitoshi Yoshida0f228c42019-08-07 09:37:421358 'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
1359 'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
Yuki Shiinoe7827aa2019-09-13 12:26:131360 'third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps',
John Budorickbc3571aa2019-04-25 02:20:061361 'tools/binary_size/sizes.pydeps',
Andrew Grievea7f1ee902018-05-18 16:17:221362 'tools/binary_size/supersize.pydeps',
agrievef32bcc72016-04-04 14:57:401363]
1364
wnwenbdc444e2016-05-25 13:44:151365
agrievef32bcc72016-04-04 14:57:401366_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
1367
1368
Eric Boren6fd2b932018-01-25 15:05:081369# Bypass the AUTHORS check for these accounts.
1370_KNOWN_ROBOTS = set(
Chan52654f52018-03-21 21:02:291371 '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
1372 for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
Eric Boren36af476a2018-06-08 16:21:081373 'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
Eric Boren57cc805b2018-08-20 17:28:321374 'spirv', 'src-internal', 'webrtc')
Sergiy Byelozyorov47158a52018-06-13 22:38:591375 ) | set('%[email protected]' % s for s in ('findit-for-me',)
Achuith Bhandarkar35905562018-07-25 19:28:451376 ) | set('%[email protected]' % s for s in ('3su6n15k.default',)
Sergiy Byelozyorov47158a52018-06-13 22:38:591377 ) | set('%[email protected]' % s
Robert Ma7f024172018-11-01 20:59:221378 for s in ('v8-ci-autoroll-builder', 'wpt-autoroller',)
Eric Boren835d71f2018-09-07 21:09:041379 ) | set('%[email protected]' % s
1380 for s in ('chromium-autoroll',)
1381 ) | set('%[email protected]' % s
Eric Boren2b7e3c3c2018-09-13 18:14:301382 for s in ('chromium-internal-autoroll',))
Eric Boren6fd2b932018-01-25 15:05:081383
1384
Daniel Bratell65b033262019-04-23 08:17:061385def _IsCPlusPlusFile(input_api, file_path):
1386 """Returns True if this file contains C++-like code (and not Python,
1387 Go, Java, MarkDown, ...)"""
1388
1389 ext = input_api.os_path.splitext(file_path)[1]
1390 # This list is compatible with CppChecker.IsCppFile but we should
1391 # consider adding ".c" to it. If we do that we can use this function
1392 # at more places in the code.
1393 return ext in (
1394 '.h',
1395 '.cc',
1396 '.cpp',
1397 '.m',
1398 '.mm',
1399 )
1400
1401def _IsCPlusPlusHeaderFile(input_api, file_path):
1402 return input_api.os_path.splitext(file_path)[1] == ".h"
1403
1404
1405def _IsJavaFile(input_api, file_path):
1406 return input_api.os_path.splitext(file_path)[1] == ".java"
1407
1408
1409def _IsProtoFile(input_api, file_path):
1410 return input_api.os_path.splitext(file_path)[1] == ".proto"
1411
[email protected]55459852011-08-10 15:17:191412def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
1413 """Attempts to prevent use of functions intended only for testing in
1414 non-testing code. For now this is just a best-effort implementation
1415 that ignores header files and may have some false positives. A
1416 better implementation would probably need a proper C++ parser.
1417 """
1418 # We only scan .cc files and the like, as the declaration of
1419 # for-testing functions in header files are hard to distinguish from
1420 # calls to such functions without a proper C++ parser.
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491421 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]55459852011-08-10 15:17:191422
jochenc0d4808c2015-07-27 09:25:421423 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:191424 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:091425 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:191426 exclusion_pattern = input_api.re.compile(
1427 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
1428 base_function_pattern, base_function_pattern))
1429
1430 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:441431 black_list = (_EXCLUDED_PATHS +
1432 _TEST_CODE_EXCLUDED_PATHS +
1433 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:191434 return input_api.FilterSourceFile(
1435 affected_file,
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491436 white_list=file_inclusion_pattern,
[email protected]55459852011-08-10 15:17:191437 black_list=black_list)
1438
1439 problems = []
1440 for f in input_api.AffectedSourceFiles(FilterFile):
1441 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:241442 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:031443 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:461444 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:031445 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:191446 problems.append(
[email protected]2fdd1f362013-01-16 03:56:031447 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:191448
1449 if problems:
[email protected]f7051d52013-04-02 18:31:421450 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:031451 else:
1452 return []
[email protected]55459852011-08-10 15:17:191453
1454
Vaclav Brozek7dbc28c2018-03-27 08:35:231455def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api):
1456 """This is a simplified version of
1457 _CheckNoProductionCodeUsingTestOnlyFunctions for Java files.
1458 """
1459 javadoc_start_re = input_api.re.compile(r'^\s*/\*\*')
1460 javadoc_end_re = input_api.re.compile(r'^\s*\*/')
1461 name_pattern = r'ForTest(s|ing)?'
1462 # Describes an occurrence of "ForTest*" inside a // comment.
1463 comment_re = input_api.re.compile(r'//.*%s' % name_pattern)
1464 # Catch calls.
1465 inclusion_re = input_api.re.compile(r'(%s)\s*\(' % name_pattern)
1466 # Ignore definitions. (Comments are ignored separately.)
1467 exclusion_re = input_api.re.compile(r'(%s)[^;]+\{' % name_pattern)
1468
1469 problems = []
1470 sources = lambda x: input_api.FilterSourceFile(
1471 x,
1472 black_list=(('(?i).*test', r'.*\/junit\/')
1473 + input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:491474 white_list=[r'.*\.java$']
Vaclav Brozek7dbc28c2018-03-27 08:35:231475 )
1476 for f in input_api.AffectedFiles(include_deletes=False, file_filter=sources):
1477 local_path = f.LocalPath()
1478 is_inside_javadoc = False
1479 for line_number, line in f.ChangedContents():
1480 if is_inside_javadoc and javadoc_end_re.search(line):
1481 is_inside_javadoc = False
1482 if not is_inside_javadoc and javadoc_start_re.search(line):
1483 is_inside_javadoc = True
1484 if is_inside_javadoc:
1485 continue
1486 if (inclusion_re.search(line) and
1487 not comment_re.search(line) and
1488 not exclusion_re.search(line)):
1489 problems.append(
1490 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1491
1492 if problems:
1493 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
1494 else:
1495 return []
1496
1497
[email protected]10689ca2011-09-02 02:31:541498def _CheckNoIOStreamInHeaders(input_api, output_api):
1499 """Checks to make sure no .h files include <iostream>."""
1500 files = []
1501 pattern = input_api.re.compile(r'^#include\s*<iostream>',
1502 input_api.re.MULTILINE)
1503 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1504 if not f.LocalPath().endswith('.h'):
1505 continue
1506 contents = input_api.ReadFile(f)
1507 if pattern.search(contents):
1508 files.append(f)
1509
1510 if len(files):
yolandyandaabc6d2016-04-18 18:29:391511 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:061512 'Do not #include <iostream> in header files, since it inserts static '
1513 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:541514 '#include <ostream>. See http://crbug.com/94794',
1515 files) ]
1516 return []
1517
Danil Chapovalov3518f362018-08-11 16:13:431518def _CheckNoStrCatRedefines(input_api, output_api):
1519 """Checks no windows headers with StrCat redefined are included directly."""
1520 files = []
1521 pattern_deny = input_api.re.compile(
1522 r'^#include\s*[<"](shlwapi|atlbase|propvarutil|sphelper).h[">]',
1523 input_api.re.MULTILINE)
1524 pattern_allow = input_api.re.compile(
1525 r'^#include\s"base/win/windows_defines.inc"',
1526 input_api.re.MULTILINE)
1527 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1528 contents = input_api.ReadFile(f)
1529 if pattern_deny.search(contents) and not pattern_allow.search(contents):
1530 files.append(f.LocalPath())
1531
1532 if len(files):
1533 return [output_api.PresubmitError(
1534 'Do not #include shlwapi.h, atlbase.h, propvarutil.h or sphelper.h '
1535 'directly since they pollute code with StrCat macro. Instead, '
1536 'include matching header from base/win. See http://crbug.com/856536',
1537 files) ]
1538 return []
1539
[email protected]10689ca2011-09-02 02:31:541540
[email protected]72df4e782012-06-21 16:28:181541def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:521542 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:181543 problems = []
1544 for f in input_api.AffectedFiles():
1545 if (not f.LocalPath().endswith(('.cc', '.mm'))):
1546 continue
1547
1548 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:041549 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:181550 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1551
1552 if not problems:
1553 return []
1554 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
1555 '\n'.join(problems))]
1556
Dominic Battre033531052018-09-24 15:45:341557def _CheckNoDISABLETypoInTests(input_api, output_api):
1558 """Checks to prevent attempts to disable tests with DISABLE_ prefix.
1559
1560 This test warns if somebody tries to disable a test with the DISABLE_ prefix
1561 instead of DISABLED_. To filter false positives, reports are only generated
1562 if a corresponding MAYBE_ line exists.
1563 """
1564 problems = []
1565
1566 # The following two patterns are looked for in tandem - is a test labeled
1567 # as MAYBE_ followed by a DISABLE_ (instead of the correct DISABLED)
1568 maybe_pattern = input_api.re.compile(r'MAYBE_([a-zA-Z0-9_]+)')
1569 disable_pattern = input_api.re.compile(r'DISABLE_([a-zA-Z0-9_]+)')
1570
1571 # This is for the case that a test is disabled on all platforms.
1572 full_disable_pattern = input_api.re.compile(
1573 r'^\s*TEST[^(]*\([a-zA-Z0-9_]+,\s*DISABLE_[a-zA-Z0-9_]+\)',
1574 input_api.re.MULTILINE)
1575
Katie Df13948e2018-09-25 07:33:441576 for f in input_api.AffectedFiles(False):
Dominic Battre033531052018-09-24 15:45:341577 if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
1578 continue
1579
1580 # Search for MABYE_, DISABLE_ pairs.
1581 disable_lines = {} # Maps of test name to line number.
1582 maybe_lines = {}
1583 for line_num, line in f.ChangedContents():
1584 disable_match = disable_pattern.search(line)
1585 if disable_match:
1586 disable_lines[disable_match.group(1)] = line_num
1587 maybe_match = maybe_pattern.search(line)
1588 if maybe_match:
1589 maybe_lines[maybe_match.group(1)] = line_num
1590
1591 # Search for DISABLE_ occurrences within a TEST() macro.
1592 disable_tests = set(disable_lines.keys())
1593 maybe_tests = set(maybe_lines.keys())
1594 for test in disable_tests.intersection(maybe_tests):
1595 problems.append(' %s:%d' % (f.LocalPath(), disable_lines[test]))
1596
1597 contents = input_api.ReadFile(f)
1598 full_disable_match = full_disable_pattern.search(contents)
1599 if full_disable_match:
1600 problems.append(' %s' % f.LocalPath())
1601
1602 if not problems:
1603 return []
1604 return [
1605 output_api.PresubmitPromptWarning(
1606 'Attempt to disable a test with DISABLE_ instead of DISABLED_?\n' +
1607 '\n'.join(problems))
1608 ]
1609
[email protected]72df4e782012-06-21 16:28:181610
danakj61c1aa22015-10-26 19:55:521611def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:571612 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:521613 errors = []
1614 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
1615 input_api.re.MULTILINE)
1616 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1617 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
1618 continue
1619 for lnum, line in f.ChangedContents():
1620 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:171621 errors.append(output_api.PresubmitError(
1622 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:571623 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:171624 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:521625 return errors
1626
1627
Makoto Shimazu3ad422cd2019-05-08 02:35:141628def _FindHistogramNameInChunk(histogram_name, chunk):
1629 """Tries to find a histogram name or prefix in a line.
1630
1631 Returns the existence of the histogram name, or None if it needs more chunk
1632 to determine."""
mcasasb7440c282015-02-04 14:52:191633 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
1634 # the histogram_name.
Makoto Shimazu3ad422cd2019-05-08 02:35:141635 if '<affected-histogram' in chunk:
1636 # If the tag is not completed, needs more chunk to get the name.
1637 if not '>' in chunk:
1638 return None
1639 if not 'name="' in chunk:
1640 return False
1641 # Retrieve the first portion of the chunk wrapped by double-quotations. We
1642 # expect the only attribute is the name.
1643 histogram_prefix = chunk.split('"')[1]
1644 return histogram_prefix in histogram_name
1645 # Typically the whole histogram name should in the line.
1646 return histogram_name in chunk
mcasasb7440c282015-02-04 14:52:191647
1648
1649def _CheckUmaHistogramChanges(input_api, output_api):
1650 """Check that UMA histogram names in touched lines can still be found in other
1651 lines of the patch or in histograms.xml. Note that this check would not catch
1652 the reverse: changes in histograms.xml not matched in the code itself."""
1653 touched_histograms = []
1654 histograms_xml_modifications = []
Vaclav Brozekbdac817c2018-03-24 06:30:471655 call_pattern_c = r'\bUMA_HISTOGRAM.*\('
1656 call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
1657 name_pattern = r'"(.*?)"'
1658 single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
1659 single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
1660 split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
1661 split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
1662 split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
Vaclav Brozek0e730cbd2018-03-24 06:18:171663 last_line_matched_prefix = False
mcasasb7440c282015-02-04 14:52:191664 for f in input_api.AffectedFiles():
1665 # If histograms.xml itself is modified, keep the modified lines for later.
1666 if f.LocalPath().endswith(('histograms.xml')):
1667 histograms_xml_modifications = f.ChangedContents()
1668 continue
Vaclav Brozekbdac817c2018-03-24 06:30:471669 if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
1670 single_line_re = single_line_c_re
1671 split_line_prefix_re = split_line_c_prefix_re
1672 elif f.LocalPath().endswith(('java')):
1673 single_line_re = single_line_java_re
1674 split_line_prefix_re = split_line_java_prefix_re
1675 else:
mcasasb7440c282015-02-04 14:52:191676 continue
1677 for line_num, line in f.ChangedContents():
Vaclav Brozek0e730cbd2018-03-24 06:18:171678 if last_line_matched_prefix:
1679 suffix_found = split_line_suffix_re.search(line)
1680 if suffix_found :
1681 touched_histograms.append([suffix_found.group(1), f, line_num])
1682 last_line_matched_prefix = False
1683 continue
Vaclav Brozek8a8e2e202018-03-23 22:01:061684 found = single_line_re.search(line)
mcasasb7440c282015-02-04 14:52:191685 if found:
1686 touched_histograms.append([found.group(1), f, line_num])
Vaclav Brozek0e730cbd2018-03-24 06:18:171687 continue
1688 last_line_matched_prefix = split_line_prefix_re.search(line)
mcasasb7440c282015-02-04 14:52:191689
1690 # Search for the touched histogram names in the local modifications to
1691 # histograms.xml, and, if not found, on the base histograms.xml file.
1692 unmatched_histograms = []
1693 for histogram_info in touched_histograms:
1694 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141695 chunk = ''
mcasasb7440c282015-02-04 14:52:191696 for line_num, line in histograms_xml_modifications:
Makoto Shimazu3ad422cd2019-05-08 02:35:141697 chunk += line
1698 histogram_name_found = _FindHistogramNameInChunk(histogram_info[0], chunk)
1699 if histogram_name_found is None:
1700 continue
1701 chunk = ''
mcasasb7440c282015-02-04 14:52:191702 if histogram_name_found:
1703 break
1704 if not histogram_name_found:
1705 unmatched_histograms.append(histogram_info)
1706
eromanb90c82e7e32015-04-01 15:13:491707 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:191708 problems = []
1709 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:491710 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:191711 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:451712 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:191713 histogram_name_found = False
Makoto Shimazu3ad422cd2019-05-08 02:35:141714 chunk = ''
mcasasb7440c282015-02-04 14:52:191715 for line in histograms_xml:
Makoto Shimazu3ad422cd2019-05-08 02:35:141716 chunk += line
1717 histogram_name_found = _FindHistogramNameInChunk(histogram_name,
1718 chunk)
1719 if histogram_name_found is None:
1720 continue
1721 chunk = ''
mcasasb7440c282015-02-04 14:52:191722 if histogram_name_found:
1723 break
1724 if not histogram_name_found:
1725 problems.append(' [%s:%d] %s' %
1726 (f.LocalPath(), line_num, histogram_name))
1727
1728 if not problems:
1729 return []
1730 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
1731 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:491732 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:191733
wnwenbdc444e2016-05-25 13:44:151734
yolandyandaabc6d2016-04-18 18:29:391735def _CheckFlakyTestUsage(input_api, output_api):
1736 """Check that FlakyTest annotation is our own instead of the android one"""
1737 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
1738 files = []
1739 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1740 if f.LocalPath().endswith('Test.java'):
1741 if pattern.search(input_api.ReadFile(f)):
1742 files.append(f)
1743 if len(files):
1744 return [output_api.PresubmitError(
1745 'Use org.chromium.base.test.util.FlakyTest instead of '
1746 'android.test.FlakyTest',
1747 files)]
1748 return []
mcasasb7440c282015-02-04 14:52:191749
wnwenbdc444e2016-05-25 13:44:151750
[email protected]8ea5d4b2011-09-13 21:49:221751def _CheckNoNewWStrings(input_api, output_api):
1752 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:271753 problems = []
[email protected]8ea5d4b2011-09-13 21:49:221754 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:201755 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:571756 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:341757 '/win/' in f.LocalPath() or
1758 'chrome_elf' in f.LocalPath() or
1759 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:201760 continue
[email protected]8ea5d4b2011-09-13 21:49:221761
[email protected]a11dbe9b2012-08-07 01:32:581762 allowWString = False
[email protected]b5c24292011-11-28 14:38:201763 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:581764 if 'presubmit: allow wstring' in line:
1765 allowWString = True
1766 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:271767 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:581768 allowWString = False
1769 else:
1770 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:221771
[email protected]55463aa62011-10-12 00:48:271772 if not problems:
1773 return []
1774 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:581775 ' If you are calling a cross-platform API that accepts a wstring, '
1776 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:271777 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:221778
1779
[email protected]2a8ac9c2011-10-19 17:20:441780def _CheckNoDEPSGIT(input_api, output_api):
1781 """Make sure .DEPS.git is never modified manually."""
1782 if any(f.LocalPath().endswith('.DEPS.git') for f in
1783 input_api.AffectedFiles()):
1784 return [output_api.PresubmitError(
1785 'Never commit changes to .DEPS.git. This file is maintained by an\n'
1786 'automated system based on what\'s in DEPS and your changes will be\n'
1787 'overwritten.\n'
Vaclav Brozekd5de76a2018-03-17 07:57:501788 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/'
1789 'get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:441790 'for more information')]
1791 return []
1792
1793
tandriief664692014-09-23 14:51:471794def _CheckValidHostsInDEPS(input_api, output_api):
1795 """Checks that DEPS file deps are from allowed_hosts."""
1796 # Run only if DEPS file has been modified to annoy fewer bystanders.
1797 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
1798 return []
1799 # Outsource work to gclient verify
1800 try:
John Budorickf20c0042019-04-25 23:23:401801 gclient_path = input_api.os_path.join(
1802 input_api.PresubmitLocalPath(),
1803 'third_party', 'depot_tools', 'gclient.py')
1804 input_api.subprocess.check_output(
1805 [input_api.python_executable, gclient_path, 'verify'],
1806 stderr=input_api.subprocess.STDOUT)
tandriief664692014-09-23 14:51:471807 return []
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:201808 except input_api.subprocess.CalledProcessError as error:
tandriief664692014-09-23 14:51:471809 return [output_api.PresubmitError(
1810 'DEPS file must have only git dependencies.',
1811 long_text=error.output)]
1812
1813
Mario Sanchez Prada2472cab2019-09-18 10:58:311814def _GetMessageForMatchingType(input_api, affected_file, line_number, line,
1815 type_name, message):
1816 """Helper method for _CheckNoBannedFunctions and _CheckNoDeprecatedMojoTypes.
1817
1818 Returns an string composed of the name of the file, the line number where the
1819 match has been found and the additional text passed as |message| in case the
1820 target type name matches the text inside the line passed as parameter.
1821 """
1822 matched = False
1823 if type_name[0:1] == '/':
1824 regex = type_name[1:]
1825 if input_api.re.search(regex, line):
1826 matched = True
1827 elif type_name in line:
1828 matched = True
1829
1830 result = []
1831 if matched:
1832 result.append(' %s:%d:' % (affected_file.LocalPath(), line_number))
1833 for message_line in message:
1834 result.append(' %s' % message_line)
1835
1836 return result
1837
1838
[email protected]127f18ec2012-06-16 05:05:591839def _CheckNoBannedFunctions(input_api, output_api):
1840 """Make sure that banned functions are not used."""
1841 warnings = []
1842 errors = []
1843
wnwenbdc444e2016-05-25 13:44:151844 def IsBlacklisted(affected_file, blacklist):
1845 local_path = affected_file.LocalPath()
1846 for item in blacklist:
1847 if input_api.re.match(item, local_path):
1848 return True
1849 return False
1850
Peter K. Lee6c03ccff2019-07-15 14:40:051851 def IsIosObjcFile(affected_file):
Sylvain Defresnea8b73d252018-02-28 15:45:541852 local_path = affected_file.LocalPath()
1853 if input_api.os_path.splitext(local_path)[-1] not in ('.mm', '.m', '.h'):
1854 return False
1855 basename = input_api.os_path.basename(local_path)
1856 if 'ios' in basename.split('_'):
1857 return True
1858 for sep in (input_api.os_path.sep, input_api.os_path.altsep):
1859 if sep and 'ios' in local_path.split(sep):
1860 return True
1861 return False
1862
wnwenbdc444e2016-05-25 13:44:151863 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
Mario Sanchez Prada2472cab2019-09-18 10:58:311864 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1865 func_name, message)
1866 if problems:
wnwenbdc444e2016-05-25 13:44:151867 if error:
Mario Sanchez Prada2472cab2019-09-18 10:58:311868 errors.extend(problems)
1869 else:
1870 warnings.extend(problems)
wnwenbdc444e2016-05-25 13:44:151871
Eric Stevensona9a980972017-09-23 00:04:411872 file_filter = lambda f: f.LocalPath().endswith(('.java'))
1873 for f in input_api.AffectedFiles(file_filter=file_filter):
1874 for line_num, line in f.ChangedContents():
1875 for func_name, message, error in _BANNED_JAVA_FUNCTIONS:
1876 CheckForMatch(f, line_num, line, func_name, message, error)
1877
[email protected]127f18ec2012-06-16 05:05:591878 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
1879 for f in input_api.AffectedFiles(file_filter=file_filter):
1880 for line_num, line in f.ChangedContents():
1881 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:151882 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591883
Peter K. Lee6c03ccff2019-07-15 14:40:051884 for f in input_api.AffectedFiles(file_filter=IsIosObjcFile):
Sylvain Defresnea8b73d252018-02-28 15:45:541885 for line_num, line in f.ChangedContents():
1886 for func_name, message, error in _BANNED_IOS_OBJC_FUNCTIONS:
1887 CheckForMatch(f, line_num, line, func_name, message, error)
1888
Peter K. Lee6c03ccff2019-07-15 14:40:051889 egtest_filter = lambda f: f.LocalPath().endswith(('_egtest.mm'))
1890 for f in input_api.AffectedFiles(file_filter=egtest_filter):
1891 for line_num, line in f.ChangedContents():
1892 for func_name, message, error in _BANNED_IOS_EGTEST_FUNCTIONS:
1893 CheckForMatch(f, line_num, line, func_name, message, error)
1894
[email protected]127f18ec2012-06-16 05:05:591895 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1896 for f in input_api.AffectedFiles(file_filter=file_filter):
1897 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:491898 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:491899 if IsBlacklisted(f, excluded_paths):
1900 continue
wnwenbdc444e2016-05-25 13:44:151901 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:591902
1903 result = []
1904 if (warnings):
1905 result.append(output_api.PresubmitPromptWarning(
1906 'Banned functions were used.\n' + '\n'.join(warnings)))
1907 if (errors):
1908 result.append(output_api.PresubmitError(
1909 'Banned functions were used.\n' + '\n'.join(errors)))
1910 return result
1911
1912
Mario Sanchez Prada2472cab2019-09-18 10:58:311913def _CheckNoDeprecatedMojoTypes(input_api, output_api):
1914 """Make sure that old Mojo types are not used."""
1915 warnings = []
1916
1917 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
1918 for f in input_api.AffectedFiles(file_filter=file_filter):
1919 # Only need to check Blink for warnings for now.
1920 if not f.LocalPath().startswith('third_party/blink'):
1921 continue
1922
1923 for line_num, line in f.ChangedContents():
1924 for func_name, message in _DEPRECATED_MOJO_TYPES:
1925 problems = _GetMessageForMatchingType(input_api, f, line_num, line,
1926 func_name, message)
1927 if problems:
1928 warnings.extend(problems)
1929
1930 result = []
1931 if (warnings):
1932 result.append(output_api.PresubmitPromptWarning(
1933 'Banned Mojo types were used.\n' + '\n'.join(warnings)))
1934 return result
1935
1936
[email protected]6c063c62012-07-11 19:11:061937def _CheckNoPragmaOnce(input_api, output_api):
1938 """Make sure that banned functions are not used."""
1939 files = []
1940 pattern = input_api.re.compile(r'^#pragma\s+once',
1941 input_api.re.MULTILINE)
1942 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
1943 if not f.LocalPath().endswith('.h'):
1944 continue
1945 contents = input_api.ReadFile(f)
1946 if pattern.search(contents):
1947 files.append(f)
1948
1949 if files:
1950 return [output_api.PresubmitError(
1951 'Do not use #pragma once in header files.\n'
1952 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
1953 files)]
1954 return []
1955
[email protected]127f18ec2012-06-16 05:05:591956
[email protected]e7479052012-09-19 00:26:121957def _CheckNoTrinaryTrueFalse(input_api, output_api):
1958 """Checks to make sure we don't introduce use of foo ? true : false."""
1959 problems = []
1960 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
1961 for f in input_api.AffectedFiles():
1962 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1963 continue
1964
1965 for line_num, line in f.ChangedContents():
1966 if pattern.match(line):
1967 problems.append(' %s:%d' % (f.LocalPath(), line_num))
1968
1969 if not problems:
1970 return []
1971 return [output_api.PresubmitPromptWarning(
1972 'Please consider avoiding the "? true : false" pattern if possible.\n' +
1973 '\n'.join(problems))]
1974
1975
[email protected]55f9f382012-07-31 11:02:181976def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:281977 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:181978 change. Breaking - rules is an error, breaking ! rules is a
1979 warning.
1980 """
mohan.reddyf21db962014-10-16 12:26:471981 import sys
[email protected]55f9f382012-07-31 11:02:181982 # We need to wait until we have an input_api object and use this
1983 # roundabout construct to import checkdeps because this file is
1984 # eval-ed and thus doesn't have __file__.
1985 original_sys_path = sys.path
1986 try:
1987 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:471988 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:181989 import checkdeps
[email protected]55f9f382012-07-31 11:02:181990 from rules import Rule
1991 finally:
1992 # Restore sys.path to what it was before.
1993 sys.path = original_sys_path
1994
1995 added_includes = []
rhalavati08acd232017-04-03 07:23:281996 added_imports = []
Jinsuk Kim5a092672017-10-24 22:42:241997 added_java_imports = []
[email protected]55f9f382012-07-31 11:02:181998 for f in input_api.AffectedFiles():
Daniel Bratell65b033262019-04-23 08:17:061999 if _IsCPlusPlusFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502000 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082001 added_includes.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062002 elif _IsProtoFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502003 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082004 added_imports.append([f.AbsoluteLocalPath(), changed_lines])
Daniel Bratell65b033262019-04-23 08:17:062005 elif _IsJavaFile(input_api, f.LocalPath()):
Vaclav Brozekd5de76a2018-03-17 07:57:502006 changed_lines = [line for _, line in f.ChangedContents()]
Andrew Grieve085f29f2017-11-02 09:14:082007 added_java_imports.append([f.AbsoluteLocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:182008
[email protected]26385172013-05-09 23:11:352009 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182010
2011 error_descriptions = []
2012 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:282013 error_subjects = set()
2014 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:182015 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
2016 added_includes):
Andrew Grieve085f29f2017-11-02 09:14:082017 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:182018 description_with_path = '%s\n %s' % (path, rule_description)
2019 if rule_type == Rule.DISALLOW:
2020 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282021 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:182022 else:
2023 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:282024 warning_subjects.add("#includes")
2025
2026 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
2027 added_imports):
Andrew Grieve085f29f2017-11-02 09:14:082028 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
rhalavati08acd232017-04-03 07:23:282029 description_with_path = '%s\n %s' % (path, rule_description)
2030 if rule_type == Rule.DISALLOW:
2031 error_descriptions.append(description_with_path)
2032 error_subjects.add("imports")
2033 else:
2034 warning_descriptions.append(description_with_path)
2035 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:182036
Jinsuk Kim5a092672017-10-24 22:42:242037 for path, rule_type, rule_description in deps_checker.CheckAddedJavaImports(
Shenghua Zhangbfaa38b82017-11-16 21:58:022038 added_java_imports, _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS):
Andrew Grieve085f29f2017-11-02 09:14:082039 path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath())
Jinsuk Kim5a092672017-10-24 22:42:242040 description_with_path = '%s\n %s' % (path, rule_description)
2041 if rule_type == Rule.DISALLOW:
2042 error_descriptions.append(description_with_path)
2043 error_subjects.add("imports")
2044 else:
2045 warning_descriptions.append(description_with_path)
2046 warning_subjects.add("imports")
2047
[email protected]55f9f382012-07-31 11:02:182048 results = []
2049 if error_descriptions:
2050 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:282051 'You added one or more %s that violate checkdeps rules.'
2052 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:182053 error_descriptions))
2054 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:422055 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:282056 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:182057 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:282058 '%s? See relevant DEPS file(s) for details and contacts.' %
2059 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:182060 warning_descriptions))
2061 return results
2062
2063
[email protected]fbcafe5a2012-08-08 15:31:222064def _CheckFilePermissions(input_api, output_api):
2065 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:152066 if input_api.platform == 'win32':
2067 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:292068 checkperms_tool = input_api.os_path.join(
2069 input_api.PresubmitLocalPath(),
2070 'tools', 'checkperms', 'checkperms.py')
2071 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:472072 '--root', input_api.change.RepositoryRoot()]
Raphael Kubo da Costa6ff391d2017-11-13 16:43:392073 with input_api.CreateTemporaryFile() as file_list:
2074 for f in input_api.AffectedFiles():
2075 # checkperms.py file/directory arguments must be relative to the
2076 # repository.
2077 file_list.write(f.LocalPath() + '\n')
2078 file_list.close()
2079 args += ['--file-list', file_list.name]
2080 try:
2081 input_api.subprocess.check_output(args)
2082 return []
2083 except input_api.subprocess.CalledProcessError as error:
2084 return [output_api.PresubmitError(
2085 'checkperms.py failed:',
2086 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:222087
2088
robertocn832f5992017-01-04 19:01:302089def _CheckTeamTags(input_api, output_api):
2090 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
2091 checkteamtags_tool = input_api.os_path.join(
2092 input_api.PresubmitLocalPath(),
2093 'tools', 'checkteamtags', 'checkteamtags.py')
2094 args = [input_api.python_executable, checkteamtags_tool,
2095 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:222096 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:302097 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
2098 'OWNERS']
2099 try:
2100 if files:
Roberto Carrillo8465e7a2019-07-17 18:39:052101 warnings = input_api.subprocess.check_output(args + files).splitlines()
2102 if warnings:
2103 return [output_api.PresubmitPromptWarning(warnings[0], warnings[1:])]
robertocn832f5992017-01-04 19:01:302104 return []
2105 except input_api.subprocess.CalledProcessError as error:
2106 return [output_api.PresubmitError(
2107 'checkteamtags.py failed:',
2108 long_text=error.output)]
2109
2110
[email protected]c8278b32012-10-30 20:35:492111def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
2112 """Makes sure we don't include ui/aura/window_property.h
2113 in header files.
2114 """
2115 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
2116 errors = []
2117 for f in input_api.AffectedFiles():
2118 if not f.LocalPath().endswith('.h'):
2119 continue
2120 for line_num, line in f.ChangedContents():
2121 if pattern.match(line):
2122 errors.append(' %s:%d' % (f.LocalPath(), line_num))
2123
2124 results = []
2125 if errors:
2126 results.append(output_api.PresubmitError(
2127 'Header files should not include ui/aura/window_property.h', errors))
2128 return results
2129
2130
[email protected]70ca77752012-11-20 03:45:032131def _CheckForVersionControlConflictsInFile(input_api, f):
2132 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
2133 errors = []
2134 for line_num, line in f.ChangedContents():
Luke Zielinski9bc14ac72019-03-04 19:02:162135 if f.LocalPath().endswith(('.md', '.rst', '.txt')):
dbeam95c35a2f2015-06-02 01:40:232136 # First-level headers in markdown look a lot like version control
2137 # conflict markers. http://daringfireball.net/projects/markdown/basics
2138 continue
[email protected]70ca77752012-11-20 03:45:032139 if pattern.match(line):
2140 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2141 return errors
2142
2143
2144def _CheckForVersionControlConflicts(input_api, output_api):
2145 """Usually this is not intentional and will cause a compile failure."""
2146 errors = []
2147 for f in input_api.AffectedFiles():
2148 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
2149
2150 results = []
2151 if errors:
2152 results.append(output_api.PresubmitError(
2153 'Version control conflict markers found, please resolve.', errors))
2154 return results
2155
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:202156
estadee17314a02017-01-12 16:22:162157def _CheckGoogleSupportAnswerUrl(input_api, output_api):
2158 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
2159 errors = []
2160 for f in input_api.AffectedFiles():
2161 for line_num, line in f.ChangedContents():
2162 if pattern.search(line):
2163 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
2164
2165 results = []
2166 if errors:
2167 results.append(output_api.PresubmitPromptWarning(
Vaclav Brozekd5de76a2018-03-17 07:57:502168 'Found Google support URL addressed by answer number. Please replace '
2169 'with a p= identifier instead. See crbug.com/679462\n', errors))
estadee17314a02017-01-12 16:22:162170 return results
2171
[email protected]70ca77752012-11-20 03:45:032172
[email protected]06e6d0ff2012-12-11 01:36:442173def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
2174 def FilterFile(affected_file):
2175 """Filter function for use with input_api.AffectedSourceFiles,
2176 below. This filters out everything except non-test files from
2177 top-level directories that generally speaking should not hard-code
2178 service URLs (e.g. src/android_webview/, src/content/ and others).
2179 """
2180 return input_api.FilterSourceFile(
2181 affected_file,
Egor Paskoce145c42018-09-28 19:31:042182 white_list=[r'^(android_webview|base|content|net)[\\/].*'],
[email protected]06e6d0ff2012-12-11 01:36:442183 black_list=(_EXCLUDED_PATHS +
2184 _TEST_CODE_EXCLUDED_PATHS +
2185 input_api.DEFAULT_BLACK_LIST))
2186
reillyi38965732015-11-16 18:27:332187 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
2188 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:462189 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
2190 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:442191 problems = [] # items are (filename, line_number, line)
2192 for f in input_api.AffectedSourceFiles(FilterFile):
2193 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:462194 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:442195 problems.append((f.LocalPath(), line_num, line))
2196
2197 if problems:
[email protected]f7051d52013-04-02 18:31:422198 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:442199 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:582200 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:442201 [' %s:%d: %s' % (
2202 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:032203 else:
2204 return []
[email protected]06e6d0ff2012-12-11 01:36:442205
2206
James Cook6b6597c2019-11-06 22:05:292207def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
2208 """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
2209 def FileFilter(affected_file):
2210 """Includes directories known to be Chrome OS only."""
2211 return input_api.FilterSourceFile(
2212 affected_file,
2213 white_list=('^ash/',
2214 '^chromeos/', # Top-level src/chromeos.
2215 '/chromeos/', # Any path component.
2216 '^components/arc',
2217 '^components/exo'),
2218 black_list=(input_api.DEFAULT_BLACK_LIST))
2219
2220 prefs = []
2221 priority_prefs = []
2222 for f in input_api.AffectedFiles(file_filter=FileFilter):
2223 for line_num, line in f.ChangedContents():
2224 if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
2225 prefs.append(' %s:%d:' % (f.LocalPath(), line_num))
2226 prefs.append(' %s' % line)
2227 if input_api.re.search(
2228 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
2229 priority_prefs.append(' %s:%d' % (f.LocalPath(), line_num))
2230 priority_prefs.append(' %s' % line)
2231
2232 results = []
2233 if (prefs):
2234 results.append(output_api.PresubmitPromptWarning(
2235 'Preferences were registered as SYNCABLE_PREF and will be controlled '
2236 'by browser sync settings. If these prefs should be controlled by OS '
2237 'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
2238 if (priority_prefs):
2239 results.append(output_api.PresubmitPromptWarning(
2240 'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
2241 'controlled by browser sync settings. If these prefs should be '
2242 'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
2243 'instead.\n' + '\n'.join(prefs)))
2244 return results
2245
2246
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492247# TODO: add unit tests.
[email protected]d2530012013-01-25 16:39:272248def _CheckNoAbbreviationInPngFileName(input_api, output_api):
2249 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:312250 The native_client_sdk directory is excluded because it has auto-generated PNG
2251 files for documentation.
[email protected]d2530012013-01-25 16:39:272252 """
[email protected]d2530012013-01-25 16:39:272253 errors = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492254 white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$']
Egor Paskoce145c42018-09-28 19:31:042255 black_list = [r'^native_client_sdk[\\/]']
binji0dcdf342014-12-12 18:32:312256 file_filter = lambda f: input_api.FilterSourceFile(
2257 f, white_list=white_list, black_list=black_list)
2258 for f in input_api.AffectedFiles(include_deletes=False,
2259 file_filter=file_filter):
2260 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:272261
2262 results = []
2263 if errors:
2264 results.append(output_api.PresubmitError(
2265 'The name of PNG files should not have abbreviations. \n'
2266 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
2267 'Contact [email protected] if you have questions.', errors))
2268 return results
2269
2270
Daniel Cheng4dcdb6b2017-04-13 08:30:172271def _ExtractAddRulesFromParsedDeps(parsed_deps):
2272 """Extract the rules that add dependencies from a parsed DEPS file.
2273
2274 Args:
2275 parsed_deps: the locals dictionary from evaluating the DEPS file."""
2276 add_rules = set()
2277 add_rules.update([
2278 rule[1:] for rule in parsed_deps.get('include_rules', [])
2279 if rule.startswith('+') or rule.startswith('!')
2280 ])
Vaclav Brozekd5de76a2018-03-17 07:57:502281 for _, rules in parsed_deps.get('specific_include_rules',
Daniel Cheng4dcdb6b2017-04-13 08:30:172282 {}).iteritems():
2283 add_rules.update([
2284 rule[1:] for rule in rules
2285 if rule.startswith('+') or rule.startswith('!')
2286 ])
2287 return add_rules
2288
2289
2290def _ParseDeps(contents):
2291 """Simple helper for parsing DEPS files."""
2292 # Stubs for handling special syntax in the root DEPS file.
Daniel Cheng4dcdb6b2017-04-13 08:30:172293 class _VarImpl:
2294
2295 def __init__(self, local_scope):
2296 self._local_scope = local_scope
2297
2298 def Lookup(self, var_name):
2299 """Implements the Var syntax."""
2300 try:
2301 return self._local_scope['vars'][var_name]
2302 except KeyError:
2303 raise Exception('Var is not defined: %s' % var_name)
2304
2305 local_scope = {}
2306 global_scope = {
Daniel Cheng4dcdb6b2017-04-13 08:30:172307 'Var': _VarImpl(local_scope).Lookup,
2308 }
2309 exec contents in global_scope, local_scope
2310 return local_scope
2311
2312
2313def _CalculateAddedDeps(os_path, old_contents, new_contents):
[email protected]f32e2d1e2013-07-26 21:39:082314 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:412315 a set of DEPS entries that we should look up.
2316
2317 For a directory (rather than a specific filename) we fake a path to
2318 a specific filename by adding /DEPS. This is chosen as a file that
2319 will seldom or never be subject to per-file include_rules.
2320 """
[email protected]2b438d62013-11-14 17:54:142321 # We ignore deps entries on auto-generated directories.
2322 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:082323
Daniel Cheng4dcdb6b2017-04-13 08:30:172324 old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents))
2325 new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents))
2326
2327 added_deps = new_deps.difference(old_deps)
2328
[email protected]2b438d62013-11-14 17:54:142329 results = set()
Daniel Cheng4dcdb6b2017-04-13 08:30:172330 for added_dep in added_deps:
2331 if added_dep.split('/')[0] in AUTO_GENERATED_DIRS:
2332 continue
2333 # Assume that a rule that ends in .h is a rule for a specific file.
2334 if added_dep.endswith('.h'):
2335 results.add(added_dep)
2336 else:
2337 results.add(os_path.join(added_dep, 'DEPS'))
[email protected]f32e2d1e2013-07-26 21:39:082338 return results
2339
2340
[email protected]e871964c2013-05-13 14:14:552341def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
2342 """When a dependency prefixed with + is added to a DEPS file, we
2343 want to make sure that the change is reviewed by an OWNER of the
2344 target file or directory, to avoid layering violations from being
2345 introduced. This check verifies that this happens.
2346 """
Daniel Cheng4dcdb6b2017-04-13 08:30:172347 virtual_depended_on_files = set()
jochen53efcdd2016-01-29 05:09:242348
2349 file_filter = lambda f: not input_api.re.match(
Kent Tamura32dbbcb2018-11-30 12:28:492350 r"^third_party[\\/]blink[\\/].*", f.LocalPath())
jochen53efcdd2016-01-29 05:09:242351 for f in input_api.AffectedFiles(include_deletes=False,
2352 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:552353 filename = input_api.os_path.basename(f.LocalPath())
2354 if filename == 'DEPS':
Daniel Cheng4dcdb6b2017-04-13 08:30:172355 virtual_depended_on_files.update(_CalculateAddedDeps(
2356 input_api.os_path,
2357 '\n'.join(f.OldContents()),
2358 '\n'.join(f.NewContents())))
[email protected]e871964c2013-05-13 14:14:552359
[email protected]e871964c2013-05-13 14:14:552360 if not virtual_depended_on_files:
2361 return []
2362
2363 if input_api.is_committing:
2364 if input_api.tbr:
2365 return [output_api.PresubmitNotifyResult(
2366 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:272367 if input_api.dry_run:
2368 return [output_api.PresubmitNotifyResult(
2369 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:552370 if not input_api.change.issue:
2371 return [output_api.PresubmitError(
2372 "DEPS approval by OWNERS check failed: this change has "
Aaron Gable65a99d92017-10-09 19:17:402373 "no change number, so we can't check it for approvals.")]
[email protected]e871964c2013-05-13 14:14:552374 output = output_api.PresubmitError
2375 else:
2376 output = output_api.PresubmitNotifyResult
2377
2378 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:502379 owner_email, reviewers = (
2380 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
2381 input_api,
2382 owners_db.email_regexp,
2383 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:552384
2385 owner_email = owner_email or input_api.change.author_email
2386
[email protected]de4f7d22013-05-23 14:27:462387 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:512388 if owner_email:
[email protected]de4f7d22013-05-23 14:27:462389 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:552390 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
2391 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:412392
2393 # We strip the /DEPS part that was added by
2394 # _FilesToCheckForIncomingDeps to fake a path to a file in a
2395 # directory.
2396 def StripDeps(path):
2397 start_deps = path.rfind('/DEPS')
2398 if start_deps != -1:
2399 return path[:start_deps]
2400 else:
2401 return path
2402 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:552403 for path in missing_files]
2404
2405 if unapproved_dependencies:
2406 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:152407 output('You need LGTM from owners of depends-on paths in DEPS that were '
2408 'modified in this CL:\n %s' %
2409 '\n '.join(sorted(unapproved_dependencies)))]
2410 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
2411 output_list.append(output(
2412 'Suggested missing target path OWNERS:\n %s' %
2413 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:552414 return output_list
2415
2416 return []
2417
2418
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492419# TODO: add unit tests.
[email protected]85218562013-11-22 07:41:402420def _CheckSpamLogging(input_api, output_api):
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492421 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
[email protected]85218562013-11-22 07:41:402422 black_list = (_EXCLUDED_PATHS +
2423 _TEST_CODE_EXCLUDED_PATHS +
2424 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:042425 (r"^base[\\/]logging\.h$",
2426 r"^base[\\/]logging\.cc$",
Francois Doray177da2c2019-06-20 14:14:222427 r"^base[\\/]task[\\/]thread_pool[\\/]task_tracker\.cc$",
Egor Paskoce145c42018-09-28 19:31:042428 r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$",
2429 r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$",
2430 r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]"
[email protected]4de75262013-12-18 23:16:122431 r"startup_browser_creator\.cc$",
Nicolas Ouellet-Payeur16730ab2019-04-09 15:39:182432 r"^chrome[\\/]browser[\\/]browser_switcher[\\/]bho[\\/].*",
Patrick Monette0196be22019-05-10 03:33:152433 r"^chrome[\\/]browser[\\/]diagnostics[\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:032434 r"diagnostics_writer\.cc$",
Patrick Monette0196be22019-05-10 03:33:152435 r"^chrome[\\/]chrome_cleaner[\\/].*",
2436 r"^chrome[\\/]chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$",
2437 r"^chrome[\\/]installer[\\/]setup[\\/].*",
Egor Paskoce145c42018-09-28 19:31:042438 r"^chromecast[\\/]",
2439 r"^cloud_print[\\/]",
2440 r"^components[\\/]browser_watcher[\\/]"
manzagop85e629e2017-05-09 22:11:482441 r"dump_stability_report_main_win.cc$",
Egor Paskoce145c42018-09-28 19:31:042442 r"^components[\\/]html_viewer[\\/]"
jochen34415e52015-07-10 08:34:312443 r"web_test_delegate_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042444 r"^components[\\/]zucchini[\\/].*",
peter80739bb2015-10-20 11:17:462445 # TODO(peter): Remove this exception. https://crbug.com/534537
Egor Paskoce145c42018-09-28 19:31:042446 r"^content[\\/]browser[\\/]notifications[\\/]"
peter80739bb2015-10-20 11:17:462447 r"notification_event_dispatcher_impl\.cc$",
Egor Paskoce145c42018-09-28 19:31:042448 r"^content[\\/]common[\\/]gpu[\\/]client[\\/]"
[email protected]9056e732014-01-08 06:25:252449 r"gl_helper_benchmark\.cc$",
Egor Paskoce145c42018-09-28 19:31:042450 r"^courgette[\\/]courgette_minimal_tool\.cc$",
2451 r"^courgette[\\/]courgette_tool\.cc$",
2452 r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$",
Fabrice de Gans-Riberi3fa1c0fa2019-02-08 18:55:272453 r"^fuchsia[\\/]engine[\\/]browser[\\/]frame_impl.cc$",
Wezd39b367f2019-11-05 00:37:002454 r"^fuchsia[\\/]engine[\\/]context_provider_main.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332455 r"^headless[\\/]app[\\/]headless_shell\.cc$",
Egor Paskoce145c42018-09-28 19:31:042456 r"^ipc[\\/]ipc_logging\.cc$",
2457 r"^native_client_sdk[\\/]",
2458 r"^remoting[\\/]base[\\/]logging\.h$",
2459 r"^remoting[\\/]host[\\/].*",
2460 r"^sandbox[\\/]linux[\\/].*",
DongJun Kimfebb3c22019-10-21 02:08:062461 r"^storage[\\/]browser[\\/]file_system[\\/]" +
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332462 r"dump_file_system.cc$",
Egor Paskoce145c42018-09-28 19:31:042463 r"^tools[\\/]",
2464 r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$",
2465 r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$",
Fabrice de Gans-Riberi570201a22019-01-17 23:32:332466 r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]"))
[email protected]85218562013-11-22 07:41:402467 source_file_filter = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492468 x, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]85218562013-11-22 07:41:402469
thomasanderson625d3932017-03-29 07:16:582470 log_info = set([])
2471 printf = set([])
[email protected]85218562013-11-22 07:41:402472
2473 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:582474 for _, line in f.ChangedContents():
2475 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
2476 log_info.add(f.LocalPath())
2477 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
2478 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:372479
thomasanderson625d3932017-03-29 07:16:582480 if input_api.re.search(r"\bprintf\(", line):
2481 printf.add(f.LocalPath())
2482 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
2483 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:402484
2485 if log_info:
2486 return [output_api.PresubmitError(
2487 'These files spam the console log with LOG(INFO):',
2488 items=log_info)]
2489 if printf:
2490 return [output_api.PresubmitError(
2491 'These files spam the console log with printf/fprintf:',
2492 items=printf)]
2493 return []
2494
2495
[email protected]49aa76a2013-12-04 06:59:162496def _CheckForAnonymousVariables(input_api, output_api):
2497 """These types are all expected to hold locks while in scope and
2498 so should never be anonymous (which causes them to be immediately
2499 destroyed)."""
2500 they_who_must_be_named = [
2501 'base::AutoLock',
2502 'base::AutoReset',
2503 'base::AutoUnlock',
2504 'SkAutoAlphaRestore',
2505 'SkAutoBitmapShaderInstall',
2506 'SkAutoBlitterChoose',
2507 'SkAutoBounderCommit',
2508 'SkAutoCallProc',
2509 'SkAutoCanvasRestore',
2510 'SkAutoCommentBlock',
2511 'SkAutoDescriptor',
2512 'SkAutoDisableDirectionCheck',
2513 'SkAutoDisableOvalCheck',
2514 'SkAutoFree',
2515 'SkAutoGlyphCache',
2516 'SkAutoHDC',
2517 'SkAutoLockColors',
2518 'SkAutoLockPixels',
2519 'SkAutoMalloc',
2520 'SkAutoMaskFreeImage',
2521 'SkAutoMutexAcquire',
2522 'SkAutoPathBoundsUpdate',
2523 'SkAutoPDFRelease',
2524 'SkAutoRasterClipValidate',
2525 'SkAutoRef',
2526 'SkAutoTime',
2527 'SkAutoTrace',
2528 'SkAutoUnref',
2529 ]
2530 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
2531 # bad: base::AutoLock(lock.get());
2532 # not bad: base::AutoLock lock(lock.get());
2533 bad_pattern = input_api.re.compile(anonymous)
2534 # good: new base::AutoLock(lock.get())
2535 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
2536 errors = []
2537
2538 for f in input_api.AffectedFiles():
2539 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
2540 continue
2541 for linenum, line in f.ChangedContents():
2542 if bad_pattern.search(line) and not good_pattern.search(line):
2543 errors.append('%s:%d' % (f.LocalPath(), linenum))
2544
2545 if errors:
2546 return [output_api.PresubmitError(
2547 'These lines create anonymous variables that need to be named:',
2548 items=errors)]
2549 return []
2550
2551
Peter Kasting4844e46e2018-02-23 07:27:102552def _CheckUniquePtr(input_api, output_api):
Vaclav Brozekb7fadb692018-08-30 06:39:532553 # Returns whether |template_str| is of the form <T, U...> for some types T
2554 # and U. Assumes that |template_str| is already in the form <...>.
2555 def HasMoreThanOneArg(template_str):
2556 # Level of <...> nesting.
2557 nesting = 0
2558 for c in template_str:
2559 if c == '<':
2560 nesting += 1
2561 elif c == '>':
2562 nesting -= 1
2563 elif c == ',' and nesting == 1:
2564 return True
2565 return False
2566
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492567 file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS]
Peter Kasting4844e46e2018-02-23 07:27:102568 sources = lambda affected_file: input_api.FilterSourceFile(
2569 affected_file,
2570 black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2571 input_api.DEFAULT_BLACK_LIST),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:492572 white_list=file_inclusion_pattern)
Vaclav Brozeka54c528b2018-04-06 19:23:552573
2574 # Pattern to capture a single "<...>" block of template arguments. It can
2575 # handle linearly nested blocks, such as "<std::vector<std::set<T>>>", but
2576 # cannot handle branching structures, such as "<pair<set<T>,set<U>>". The
2577 # latter would likely require counting that < and > match, which is not
2578 # expressible in regular languages. Should the need arise, one can introduce
2579 # limited counting (matching up to a total number of nesting depth), which
2580 # should cover all practical cases for already a low nesting limit.
2581 template_arg_pattern = (
2582 r'<[^>]*' # Opening block of <.
2583 r'>([^<]*>)?') # Closing block of >.
2584 # Prefix expressing that whatever follows is not already inside a <...>
2585 # block.
2586 not_inside_template_arg_pattern = r'(^|[^<,\s]\s*)'
Peter Kasting4844e46e2018-02-23 07:27:102587 null_construct_pattern = input_api.re.compile(
Vaclav Brozeka54c528b2018-04-06 19:23:552588 not_inside_template_arg_pattern
2589 + r'\bstd::unique_ptr'
2590 + template_arg_pattern
2591 + r'\(\)')
2592
2593 # Same as template_arg_pattern, but excluding type arrays, e.g., <T[]>.
2594 template_arg_no_array_pattern = (
2595 r'<[^>]*[^]]' # Opening block of <.
2596 r'>([^(<]*[^]]>)?') # Closing block of >.
2597 # Prefix saying that what follows is the start of an expression.
2598 start_of_expr_pattern = r'(=|\breturn|^)\s*'
2599 # Suffix saying that what follows are call parentheses with a non-empty list
2600 # of arguments.
2601 nonempty_arg_list_pattern = r'\(([^)]|$)'
Vaclav Brozekb7fadb692018-08-30 06:39:532602 # Put the template argument into a capture group for deeper examination later.
Vaclav Brozeka54c528b2018-04-06 19:23:552603 return_construct_pattern = input_api.re.compile(
2604 start_of_expr_pattern
2605 + r'std::unique_ptr'
Vaclav Brozekb7fadb692018-08-30 06:39:532606 + '(?P<template_arg>'
Vaclav Brozeka54c528b2018-04-06 19:23:552607 + template_arg_no_array_pattern
Vaclav Brozekb7fadb692018-08-30 06:39:532608 + ')'
Vaclav Brozeka54c528b2018-04-06 19:23:552609 + nonempty_arg_list_pattern)
2610
Vaclav Brozek851d9602018-04-04 16:13:052611 problems_constructor = []
2612 problems_nullptr = []
Peter Kasting4844e46e2018-02-23 07:27:102613 for f in input_api.AffectedSourceFiles(sources):
2614 for line_number, line in f.ChangedContents():
2615 # Disallow:
2616 # return std::unique_ptr<T>(foo);
2617 # bar = std::unique_ptr<T>(foo);
2618 # But allow:
2619 # return std::unique_ptr<T[]>(foo);
2620 # bar = std::unique_ptr<T[]>(foo);
Vaclav Brozekb7fadb692018-08-30 06:39:532621 # And also allow cases when the second template argument is present. Those
2622 # cases cannot be handled by std::make_unique:
2623 # return std::unique_ptr<T, U>(foo);
2624 # bar = std::unique_ptr<T, U>(foo);
Vaclav Brozek851d9602018-04-04 16:13:052625 local_path = f.LocalPath()
Vaclav Brozekb7fadb692018-08-30 06:39:532626 return_construct_result = return_construct_pattern.search(line)
2627 if return_construct_result and not HasMoreThanOneArg(
2628 return_construct_result.group('template_arg')):
Vaclav Brozek851d9602018-04-04 16:13:052629 problems_constructor.append(
2630 '%s:%d\n %s' % (local_path, line_number, line.strip()))
Peter Kasting4844e46e2018-02-23 07:27:102631 # Disallow:
2632 # std::unique_ptr<T>()
2633 if null_construct_pattern.search(line):
Vaclav Brozek851d9602018-04-04 16:13:052634 problems_nullptr.append(
2635 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2636
2637 errors = []
Vaclav Brozekc2fecf42018-04-06 16:40:162638 if problems_nullptr:
Vaclav Brozek851d9602018-04-04 16:13:052639 errors.append(output_api.PresubmitError(
2640 'The following files use std::unique_ptr<T>(). Use nullptr instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162641 problems_nullptr))
2642 if problems_constructor:
Vaclav Brozek851d9602018-04-04 16:13:052643 errors.append(output_api.PresubmitError(
2644 'The following files use explicit std::unique_ptr constructor.'
2645 'Use std::make_unique<T>() instead.',
Vaclav Brozekc2fecf42018-04-06 16:40:162646 problems_constructor))
Peter Kasting4844e46e2018-02-23 07:27:102647 return errors
2648
2649
[email protected]999261d2014-03-03 20:08:082650def _CheckUserActionUpdate(input_api, output_api):
2651 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:522652 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:082653 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:522654 # If actions.xml is already included in the changelist, the PRESUBMIT
2655 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:082656 return []
2657
[email protected]999261d2014-03-03 20:08:082658 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
2659 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:522660 current_actions = None
[email protected]999261d2014-03-03 20:08:082661 for f in input_api.AffectedFiles(file_filter=file_filter):
2662 for line_num, line in f.ChangedContents():
2663 match = input_api.re.search(action_re, line)
2664 if match:
[email protected]2f92dec2014-03-07 19:21:522665 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
2666 # loaded only once.
2667 if not current_actions:
2668 with open('tools/metrics/actions/actions.xml') as actions_f:
2669 current_actions = actions_f.read()
2670 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:082671 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:522672 action = 'name="{0}"'.format(action_name)
2673 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:082674 return [output_api.PresubmitPromptWarning(
2675 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:522676 'tools/metrics/actions/actions.xml. Please run '
2677 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:082678 % (f.LocalPath(), line_num, action_name))]
2679 return []
2680
2681
Daniel Cheng13ca61a882017-08-25 15:11:252682def _ImportJSONCommentEater(input_api):
2683 import sys
2684 sys.path = sys.path + [input_api.os_path.join(
2685 input_api.PresubmitLocalPath(),
2686 'tools', 'json_comment_eater')]
2687 import json_comment_eater
2688 return json_comment_eater
2689
2690
[email protected]99171a92014-06-03 08:44:472691def _GetJSONParseError(input_api, filename, eat_comments=True):
2692 try:
2693 contents = input_api.ReadFile(filename)
2694 if eat_comments:
Daniel Cheng13ca61a882017-08-25 15:11:252695 json_comment_eater = _ImportJSONCommentEater(input_api)
plundblad1f5a4509f2015-07-23 11:31:132696 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:472697
2698 input_api.json.loads(contents)
2699 except ValueError as e:
2700 return e
2701 return None
2702
2703
2704def _GetIDLParseError(input_api, filename):
2705 try:
2706 contents = input_api.ReadFile(filename)
2707 idl_schema = input_api.os_path.join(
2708 input_api.PresubmitLocalPath(),
2709 'tools', 'json_schema_compiler', 'idl_schema.py')
2710 process = input_api.subprocess.Popen(
2711 [input_api.python_executable, idl_schema],
2712 stdin=input_api.subprocess.PIPE,
2713 stdout=input_api.subprocess.PIPE,
2714 stderr=input_api.subprocess.PIPE,
2715 universal_newlines=True)
2716 (_, error) = process.communicate(input=contents)
2717 return error or None
2718 except ValueError as e:
2719 return e
2720
2721
2722def _CheckParseErrors(input_api, output_api):
2723 """Check that IDL and JSON files do not contain syntax errors."""
2724 actions = {
2725 '.idl': _GetIDLParseError,
2726 '.json': _GetJSONParseError,
2727 }
[email protected]99171a92014-06-03 08:44:472728 # Most JSON files are preprocessed and support comments, but these do not.
2729 json_no_comments_patterns = [
Egor Paskoce145c42018-09-28 19:31:042730 r'^testing[\\/]',
[email protected]99171a92014-06-03 08:44:472731 ]
2732 # Only run IDL checker on files in these directories.
2733 idl_included_patterns = [
Egor Paskoce145c42018-09-28 19:31:042734 r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]',
2735 r'^extensions[\\/]common[\\/]api[\\/]',
[email protected]99171a92014-06-03 08:44:472736 ]
2737
2738 def get_action(affected_file):
2739 filename = affected_file.LocalPath()
2740 return actions.get(input_api.os_path.splitext(filename)[1])
2741
[email protected]99171a92014-06-03 08:44:472742 def FilterFile(affected_file):
2743 action = get_action(affected_file)
2744 if not action:
2745 return False
2746 path = affected_file.LocalPath()
2747
Sean Kau46e29bc2017-08-28 16:31:162748 if _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS, path):
[email protected]99171a92014-06-03 08:44:472749 return False
2750
2751 if (action == _GetIDLParseError and
Sean Kau46e29bc2017-08-28 16:31:162752 not _MatchesFile(input_api, idl_included_patterns, path)):
[email protected]99171a92014-06-03 08:44:472753 return False
2754 return True
2755
2756 results = []
2757 for affected_file in input_api.AffectedFiles(
2758 file_filter=FilterFile, include_deletes=False):
2759 action = get_action(affected_file)
2760 kwargs = {}
2761 if (action == _GetJSONParseError and
Sean Kau46e29bc2017-08-28 16:31:162762 _MatchesFile(input_api, json_no_comments_patterns,
2763 affected_file.LocalPath())):
[email protected]99171a92014-06-03 08:44:472764 kwargs['eat_comments'] = False
2765 parse_error = action(input_api,
2766 affected_file.AbsoluteLocalPath(),
2767 **kwargs)
2768 if parse_error:
2769 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
2770 (affected_file.LocalPath(), parse_error)))
2771 return results
2772
2773
[email protected]760deea2013-12-10 19:33:492774def _CheckJavaStyle(input_api, output_api):
2775 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:472776 import sys
[email protected]760deea2013-12-10 19:33:492777 original_sys_path = sys.path
2778 try:
2779 sys.path = sys.path + [input_api.os_path.join(
2780 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
2781 import checkstyle
2782 finally:
2783 # Restore sys.path to what it was before.
2784 sys.path = original_sys_path
2785
2786 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:092787 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:512788 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:492789
2790
Nate Fischerdfd9812e2019-07-18 22:03:002791def _CheckPythonDevilInit(input_api, output_api):
2792 """Checks to make sure devil is initialized correctly in python scripts."""
2793 script_common_initialize_pattern = input_api.re.compile(
2794 r'script_common\.InitializeEnvironment\(')
2795 devil_env_config_initialize = input_api.re.compile(
2796 r'devil_env\.config\.Initialize\(')
2797
2798 errors = []
2799
2800 sources = lambda affected_file: input_api.FilterSourceFile(
2801 affected_file,
2802 black_list=(_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST +
2803 (r'^build[\\/]android[\\/]devil_chromium\.py',
2804 r'^third_party[\\/].*',)),
2805 white_list=[r'.*\.py$'])
2806
2807 for f in input_api.AffectedSourceFiles(sources):
2808 for line_num, line in f.ChangedContents():
2809 if (script_common_initialize_pattern.search(line) or
2810 devil_env_config_initialize.search(line)):
2811 errors.append("%s:%d" % (f.LocalPath(), line_num))
2812
2813 results = []
2814
2815 if errors:
2816 results.append(output_api.PresubmitError(
2817 'Devil initialization should always be done using '
2818 'devil_chromium.Initialize() in the chromium project, to use better '
2819 'defaults for dependencies (ex. up-to-date version of adb).',
2820 errors))
2821
2822 return results
2823
2824
Sean Kau46e29bc2017-08-28 16:31:162825def _MatchesFile(input_api, patterns, path):
2826 for pattern in patterns:
2827 if input_api.re.search(pattern, path):
2828 return True
2829 return False
2830
2831
Daniel Cheng7052cdf2017-11-21 19:23:292832def _GetOwnersFilesToCheckForIpcOwners(input_api):
2833 """Gets a list of OWNERS files to check for correct security owners.
dchenge07de812016-06-20 19:27:172834
Daniel Cheng7052cdf2017-11-21 19:23:292835 Returns:
2836 A dictionary mapping an OWNER file to the list of OWNERS rules it must
2837 contain to cover IPC-related files with noparent reviewer rules.
2838 """
2839 # Whether or not a file affects IPC is (mostly) determined by a simple list
2840 # of filename patterns.
dchenge07de812016-06-20 19:27:172841 file_patterns = [
palmerb19a0932017-01-24 04:00:312842 # Legacy IPC:
dchenge07de812016-06-20 19:27:172843 '*_messages.cc',
2844 '*_messages*.h',
2845 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:312846 # Mojo IPC:
dchenge07de812016-06-20 19:27:172847 '*.mojom',
Daniel Cheng1f386932018-01-29 19:56:472848 '*_mojom_traits*.*',
dchenge07de812016-06-20 19:27:172849 '*_struct_traits*.*',
2850 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:312851 '*.typemap',
2852 # Android native IPC:
2853 '*.aidl',
2854 # Blink uses a different file naming convention:
2855 '*EnumTraits*.*',
Daniel Chenge0bf3f62018-01-30 01:56:472856 "*MojomTraits*.*",
dchenge07de812016-06-20 19:27:172857 '*StructTraits*.*',
2858 '*TypeConverter*.*',
2859 ]
2860
scottmg7a6ed5ba2016-11-04 18:22:042861 # These third_party directories do not contain IPCs, but contain files
2862 # matching the above patterns, which trigger false positives.
2863 exclude_paths = [
2864 'third_party/crashpad/*',
Raphael Kubo da Costa4a224cf42019-11-19 18:44:162865 'third_party/blink/renderer/platform/bindings/*',
Andres Medinae684cf42018-08-27 18:48:232866 'third_party/protobuf/benchmarks/python/*',
Nico Weberee3dc9b2017-08-31 17:09:292867 'third_party/win_build_output/*',
Dan Harringtonb60e1aa2019-11-20 08:48:542868 'third_party/feed_library/*',
Scott Violet9f82d362019-11-06 21:42:162869 # These files are just used to communicate between class loaders running
2870 # in the same process.
2871 'weblayer/browser/java/org/chromium/weblayer_private/interfaces/*',
scottmg7a6ed5ba2016-11-04 18:22:042872 ]
2873
dchenge07de812016-06-20 19:27:172874 # Dictionary mapping an OWNERS file path to Patterns.
2875 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
2876 # rules ) to a PatternEntry.
2877 # PatternEntry is a dictionary with two keys:
2878 # - 'files': the files that are matched by this pattern
2879 # - 'rules': the per-file rules needed for this pattern
2880 # For example, if we expect OWNERS file to contain rules for *.mojom and
2881 # *_struct_traits*.*, Patterns might look like this:
2882 # {
2883 # '*.mojom': {
2884 # 'files': ...,
2885 # 'rules': [
2886 # 'per-file *.mojom=set noparent',
2887 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
2888 # ],
2889 # },
2890 # '*_struct_traits*.*': {
2891 # 'files': ...,
2892 # 'rules': [
2893 # 'per-file *_struct_traits*.*=set noparent',
2894 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
2895 # ],
2896 # },
2897 # }
2898 to_check = {}
2899
Daniel Cheng13ca61a882017-08-25 15:11:252900 def AddPatternToCheck(input_file, pattern):
2901 owners_file = input_api.os_path.join(
2902 input_api.os_path.dirname(input_file.LocalPath()), 'OWNERS')
2903 if owners_file not in to_check:
2904 to_check[owners_file] = {}
2905 if pattern not in to_check[owners_file]:
2906 to_check[owners_file][pattern] = {
2907 'files': [],
2908 'rules': [
2909 'per-file %s=set noparent' % pattern,
2910 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
2911 ]
2912 }
Vaclav Brozekd5de76a2018-03-17 07:57:502913 to_check[owners_file][pattern]['files'].append(input_file)
Daniel Cheng13ca61a882017-08-25 15:11:252914
dchenge07de812016-06-20 19:27:172915 # Iterate through the affected files to see what we actually need to check
2916 # for. We should only nag patch authors about per-file rules if a file in that
2917 # directory would match that pattern. If a directory only contains *.mojom
2918 # files and no *_messages*.h files, we should only nag about rules for
2919 # *.mojom files.
Daniel Cheng13ca61a882017-08-25 15:11:252920 for f in input_api.AffectedFiles(include_deletes=False):
2921 # Manifest files don't have a strong naming convention. Instead, scan
Ken Rockot9f668262018-12-21 18:56:362922 # affected files for .json, .cc, and .h files which look like they contain
2923 # a manifest definition.
Sean Kau46e29bc2017-08-28 16:31:162924 if (f.LocalPath().endswith('.json') and
2925 not _MatchesFile(input_api, _KNOWN_INVALID_JSON_FILE_PATTERNS,
2926 f.LocalPath())):
Daniel Cheng13ca61a882017-08-25 15:11:252927 json_comment_eater = _ImportJSONCommentEater(input_api)
2928 mostly_json_lines = '\n'.join(f.NewContents())
2929 # Comments aren't allowed in strict JSON, so filter them out.
2930 json_lines = json_comment_eater.Nom(mostly_json_lines)
Daniel Chenge8efd092018-03-23 23:57:432931 try:
2932 json_content = input_api.json.loads(json_lines)
2933 except:
2934 # There's another PRESUBMIT check that already verifies that JSON files
2935 # are not invalid, so no need to emit another warning here.
2936 continue
Daniel Cheng13ca61a882017-08-25 15:11:252937 if 'interface_provider_specs' in json_content:
2938 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
Ken Rockot9f668262018-12-21 18:56:362939 else:
2940 manifest_pattern = input_api.re.compile('manifests?\.(cc|h)$')
2941 test_manifest_pattern = input_api.re.compile('test_manifests?\.(cc|h)')
2942 if (manifest_pattern.search(f.LocalPath()) and not
2943 test_manifest_pattern.search(f.LocalPath())):
2944 # We expect all actual service manifest files to contain at least one
2945 # qualified reference to service_manager::Manifest.
2946 if 'service_manager::Manifest' in '\n'.join(f.NewContents()):
2947 AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
dchenge07de812016-06-20 19:27:172948 for pattern in file_patterns:
2949 if input_api.fnmatch.fnmatch(
2950 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:042951 skip = False
2952 for exclude in exclude_paths:
2953 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
2954 skip = True
2955 break
2956 if skip:
2957 continue
Daniel Cheng13ca61a882017-08-25 15:11:252958 AddPatternToCheck(f, pattern)
dchenge07de812016-06-20 19:27:172959 break
2960
Daniel Cheng7052cdf2017-11-21 19:23:292961 return to_check
2962
2963
2964def _CheckIpcOwners(input_api, output_api):
2965 """Checks that affected files involving IPC have an IPC OWNERS rule."""
2966 to_check = _GetOwnersFilesToCheckForIpcOwners(input_api)
2967
2968 if to_check:
2969 # If there are any OWNERS files to check, there are IPC-related changes in
2970 # this CL. Auto-CC the review list.
2971 output_api.AppendCC('[email protected]')
2972
2973 # Go through the OWNERS files to check, filtering out rules that are already
2974 # present in that OWNERS file.
dchenge07de812016-06-20 19:27:172975 for owners_file, patterns in to_check.iteritems():
2976 try:
2977 with file(owners_file) as f:
2978 lines = set(f.read().splitlines())
2979 for entry in patterns.itervalues():
2980 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
2981 ]
2982 except IOError:
2983 # No OWNERS file, so all the rules are definitely missing.
2984 continue
2985
2986 # All the remaining lines weren't found in OWNERS files, so emit an error.
2987 errors = []
2988 for owners_file, patterns in to_check.iteritems():
2989 missing_lines = []
2990 files = []
Vaclav Brozekd5de76a2018-03-17 07:57:502991 for _, entry in patterns.iteritems():
dchenge07de812016-06-20 19:27:172992 missing_lines.extend(entry['rules'])
2993 files.extend([' %s' % f.LocalPath() for f in entry['files']])
2994 if missing_lines:
2995 errors.append(
Vaclav Brozek1893a972018-04-25 05:48:052996 'Because of the presence of files:\n%s\n\n'
2997 '%s needs the following %d lines added:\n\n%s' %
2998 ('\n'.join(files), owners_file, len(missing_lines),
2999 '\n'.join(missing_lines)))
dchenge07de812016-06-20 19:27:173000
3001 results = []
3002 if errors:
vabrf5ce3bf92016-07-11 14:52:413003 if input_api.is_committing:
3004 output = output_api.PresubmitError
3005 else:
3006 output = output_api.PresubmitPromptWarning
3007 results.append(output(
Daniel Cheng52111692017-06-14 08:00:593008 'Found OWNERS files that need to be updated for IPC security ' +
3009 'review coverage.\nPlease update the OWNERS files below:',
dchenge07de812016-06-20 19:27:173010 long_text='\n\n'.join(errors)))
3011
3012 return results
3013
3014
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:263015def _CheckSetNoParent(input_api, output_api):
3016 """Checks that set noparent is only used together with an OWNERS file in
3017 //build/OWNERS.setnoparent (see also
3018 //docs/code_reviews.md#owners-files-details)
3019 """
3020 errors = []
3021
3022 allowed_owners_files_file = 'build/OWNERS.setnoparent'
3023 allowed_owners_files = set()
3024 with open(allowed_owners_files_file, 'r') as f:
3025 for line in f:
3026 line = line.strip()
3027 if not line or line.startswith('#'):
3028 continue
3029 allowed_owners_files.add(line)
3030
3031 per_file_pattern = input_api.re.compile('per-file (.+)=(.+)')
3032
3033 for f in input_api.AffectedFiles(include_deletes=False):
3034 if not f.LocalPath().endswith('OWNERS'):
3035 continue
3036
3037 found_owners_files = set()
3038 found_set_noparent_lines = dict()
3039
3040 # Parse the OWNERS file.
3041 for lineno, line in enumerate(f.NewContents(), 1):
3042 line = line.strip()
3043 if line.startswith('set noparent'):
3044 found_set_noparent_lines[''] = lineno
3045 if line.startswith('file://'):
3046 if line in allowed_owners_files:
3047 found_owners_files.add('')
3048 if line.startswith('per-file'):
3049 match = per_file_pattern.match(line)
3050 if match:
3051 glob = match.group(1).strip()
3052 directive = match.group(2).strip()
3053 if directive == 'set noparent':
3054 found_set_noparent_lines[glob] = lineno
3055 if directive.startswith('file://'):
3056 if directive in allowed_owners_files:
3057 found_owners_files.add(glob)
3058
3059 # Check that every set noparent line has a corresponding file:// line
3060 # listed in build/OWNERS.setnoparent.
3061 for set_noparent_line in found_set_noparent_lines:
3062 if set_noparent_line in found_owners_files:
3063 continue
3064 errors.append(' %s:%d' % (f.LocalPath(),
3065 found_set_noparent_lines[set_noparent_line]))
3066
3067 results = []
3068 if errors:
3069 if input_api.is_committing:
3070 output = output_api.PresubmitError
3071 else:
3072 output = output_api.PresubmitPromptWarning
3073 results.append(output(
3074 'Found the following "set noparent" restrictions in OWNERS files that '
3075 'do not include owners from build/OWNERS.setnoparent:',
3076 long_text='\n\n'.join(errors)))
3077 return results
3078
3079
jbriance9e12f162016-11-25 07:57:503080def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:313081 """Checks that added or removed lines in non third party affected
3082 header files do not lead to new useless class or struct forward
3083 declaration.
jbriance9e12f162016-11-25 07:57:503084 """
3085 results = []
3086 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
3087 input_api.re.MULTILINE)
3088 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
3089 input_api.re.MULTILINE)
3090 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:313091 if (f.LocalPath().startswith('third_party') and
Kent Tamurae9b3a9ec2017-08-31 02:20:193092 not f.LocalPath().startswith('third_party/blink') and
Kent Tamura32dbbcb2018-11-30 12:28:493093 not f.LocalPath().startswith('third_party\\blink')):
jbriance2c51e821a2016-12-12 08:24:313094 continue
3095
jbriance9e12f162016-11-25 07:57:503096 if not f.LocalPath().endswith('.h'):
3097 continue
3098
3099 contents = input_api.ReadFile(f)
3100 fwd_decls = input_api.re.findall(class_pattern, contents)
3101 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
3102
3103 useless_fwd_decls = []
3104 for decl in fwd_decls:
3105 count = sum(1 for _ in input_api.re.finditer(
3106 r'\b%s\b' % input_api.re.escape(decl), contents))
3107 if count == 1:
3108 useless_fwd_decls.append(decl)
3109
3110 if not useless_fwd_decls:
3111 continue
3112
3113 for line in f.GenerateScmDiff().splitlines():
3114 if (line.startswith('-') and not line.startswith('--') or
3115 line.startswith('+') and not line.startswith('++')):
3116 for decl in useless_fwd_decls:
3117 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
3118 results.append(output_api.PresubmitPromptWarning(
ricea6416dea2017-05-19 12:39:243119 '%s: %s forward declaration is no longer needed' %
jbriance9e12f162016-11-25 07:57:503120 (f.LocalPath(), decl)))
3121 useless_fwd_decls.remove(decl)
3122
3123 return results
3124
Jinsong Fan91ebbbd2019-04-16 14:57:173125def _CheckAndroidDebuggableBuild(input_api, output_api):
3126 """Checks that code uses BuildInfo.isDebugAndroid() instead of
3127 Build.TYPE.equals('') or ''.equals(Build.TYPE) to check if
3128 this is a debuggable build of Android.
3129 """
3130 build_type_check_pattern = input_api.re.compile(
3131 r'\bBuild\.TYPE\.equals\(|\.equals\(\s*\bBuild\.TYPE\)')
3132
3133 errors = []
3134
3135 sources = lambda affected_file: input_api.FilterSourceFile(
3136 affected_file,
3137 black_list=(_EXCLUDED_PATHS +
3138 _TEST_CODE_EXCLUDED_PATHS +
3139 input_api.DEFAULT_BLACK_LIST +
3140 (r"^android_webview[\\/]support_library[\\/]"
3141 "boundary_interfaces[\\/]",
3142 r"^chrome[\\/]android[\\/]webapk[\\/].*",
3143 r'^third_party[\\/].*',
3144 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
3145 r"webview[\\/]chromium[\\/]License.*",)),
3146 white_list=[r'.*\.java$'])
3147
3148 for f in input_api.AffectedSourceFiles(sources):
3149 for line_num, line in f.ChangedContents():
3150 if build_type_check_pattern.search(line):
3151 errors.append("%s:%d" % (f.LocalPath(), line_num))
3152
3153 results = []
3154
3155 if errors:
3156 results.append(output_api.PresubmitPromptWarning(
3157 'Build.TYPE.equals or .equals(Build.TYPE) usage is detected.'
3158 ' Please use BuildInfo.isDebugAndroid() instead.',
3159 errors))
3160
3161 return results
jbriance9e12f162016-11-25 07:57:503162
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493163# TODO: add unit tests
dskiba88634f4e2015-08-14 23:03:293164def _CheckAndroidToastUsage(input_api, output_api):
3165 """Checks that code uses org.chromium.ui.widget.Toast instead of
3166 android.widget.Toast (Chromium Toast doesn't force hardware
3167 acceleration on low-end devices, saving memory).
3168 """
3169 toast_import_pattern = input_api.re.compile(
3170 r'^import android\.widget\.Toast;$')
3171
3172 errors = []
3173
3174 sources = lambda affected_file: input_api.FilterSourceFile(
3175 affected_file,
3176 black_list=(_EXCLUDED_PATHS +
3177 _TEST_CODE_EXCLUDED_PATHS +
3178 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043179 (r'^chromecast[\\/].*',
3180 r'^remoting[\\/].*')),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493181 white_list=[r'.*\.java$'])
dskiba88634f4e2015-08-14 23:03:293182
3183 for f in input_api.AffectedSourceFiles(sources):
3184 for line_num, line in f.ChangedContents():
3185 if toast_import_pattern.search(line):
3186 errors.append("%s:%d" % (f.LocalPath(), line_num))
3187
3188 results = []
3189
3190 if errors:
3191 results.append(output_api.PresubmitError(
3192 'android.widget.Toast usage is detected. Android toasts use hardware'
3193 ' acceleration, and can be\ncostly on low-end devices. Please use'
3194 ' org.chromium.ui.widget.Toast instead.\n'
3195 'Contact [email protected] if you have any questions.',
3196 errors))
3197
3198 return results
3199
3200
dgnaa68d5e2015-06-10 10:08:223201def _CheckAndroidCrLogUsage(input_api, output_api):
3202 """Checks that new logs using org.chromium.base.Log:
3203 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:513204 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:223205 """
pkotwicza1dd0b002016-05-16 14:41:043206
torne89540622017-03-24 19:41:303207 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:043208 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:303209 # //chrome/android/webapk cannot depend on //base
Egor Paskoce145c42018-09-28 19:31:043210 r"^chrome[\\/]android[\\/]webapk[\\/].*",
torne89540622017-03-24 19:41:303211 # WebView license viewer code cannot depend on //base; used in stub APK.
Egor Paskoce145c42018-09-28 19:31:043212 r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]"
3213 r"webview[\\/]chromium[\\/]License.*",
Egor Paskoa5c05b02018-09-28 16:04:093214 # The customtabs_benchmark is a small app that does not depend on Chromium
3215 # java pieces.
Egor Paskoce145c42018-09-28 19:31:043216 r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*",
pkotwicza1dd0b002016-05-16 14:41:043217 ]
3218
dgnaa68d5e2015-06-10 10:08:223219 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:123220 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
3221 class_in_base_pattern = input_api.re.compile(
3222 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
3223 has_some_log_import_pattern = input_api.re.compile(
3224 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:223225 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:123226 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:223227 log_decl_pattern = input_api.re.compile(
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463228 r'static final String TAG = "(?P<name>(.*))"')
dgnaa68d5e2015-06-10 10:08:223229
Torne (Richard Coles)3bd7ad02019-10-22 21:20:463230 REF_MSG = ('See docs/android_logging.md for more info.')
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493231 sources = lambda x: input_api.FilterSourceFile(x, white_list=[r'.*\.java$'],
pkotwicza1dd0b002016-05-16 14:41:043232 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:123233
dgnaa68d5e2015-06-10 10:08:223234 tag_decl_errors = []
3235 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:123236 tag_errors = []
dgn38736db2015-09-18 19:20:513237 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:123238 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:223239
3240 for f in input_api.AffectedSourceFiles(sources):
3241 file_content = input_api.ReadFile(f)
3242 has_modified_logs = False
3243
3244 # Per line checks
dgn87d9fb62015-06-12 09:15:123245 if (cr_log_import_pattern.search(file_content) or
3246 (class_in_base_pattern.search(file_content) and
3247 not has_some_log_import_pattern.search(file_content))):
3248 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:223249 for line_num, line in f.ChangedContents():
3250
3251 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:123252 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:223253 if match:
3254 has_modified_logs = True
3255
3256 # Make sure it uses "TAG"
3257 if not match.group('tag') == 'TAG':
3258 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:123259 else:
3260 # Report non cr Log function calls in changed lines
3261 for line_num, line in f.ChangedContents():
3262 if log_call_pattern.search(line):
3263 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:223264
3265 # Per file checks
3266 if has_modified_logs:
3267 # Make sure the tag is using the "cr" prefix and is not too long
3268 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:513269 tag_name = match.group('name') if match else None
3270 if not tag_name:
dgnaa68d5e2015-06-10 10:08:223271 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513272 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:223273 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:513274 elif '.' in tag_name:
3275 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:223276
3277 results = []
3278 if tag_decl_errors:
3279 results.append(output_api.PresubmitPromptWarning(
3280 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:513281 '"private static final String TAG = "<package tag>".\n'
3282 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223283 tag_decl_errors))
3284
3285 if tag_length_errors:
3286 results.append(output_api.PresubmitError(
3287 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:513288 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:223289 tag_length_errors))
3290
3291 if tag_errors:
3292 results.append(output_api.PresubmitPromptWarning(
3293 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
3294 tag_errors))
3295
dgn87d9fb62015-06-12 09:15:123296 if util_log_errors:
dgn4401aa52015-04-29 16:26:173297 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:123298 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
3299 util_log_errors))
3300
dgn38736db2015-09-18 19:20:513301 if tag_with_dot_errors:
3302 results.append(output_api.PresubmitPromptWarning(
3303 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
3304 tag_with_dot_errors))
3305
dgn4401aa52015-04-29 16:26:173306 return results
3307
3308
Yoland Yanb92fa522017-08-28 17:37:063309def _CheckAndroidTestJUnitFrameworkImport(input_api, output_api):
3310 """Checks that junit.framework.* is no longer used."""
3311 deprecated_junit_framework_pattern = input_api.re.compile(
3312 r'^import junit\.framework\..*;',
3313 input_api.re.MULTILINE)
3314 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493315 x, white_list=[r'.*\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063316 errors = []
3317 for f in input_api.AffectedFiles(sources):
3318 for line_num, line in f.ChangedContents():
3319 if deprecated_junit_framework_pattern.search(line):
3320 errors.append("%s:%d" % (f.LocalPath(), line_num))
3321
3322 results = []
3323 if errors:
3324 results.append(output_api.PresubmitError(
3325 'APIs from junit.framework.* are deprecated, please use JUnit4 framework'
3326 '(org.junit.*) from //third_party/junit. Contact [email protected]'
3327 ' if you have any question.', errors))
3328 return results
3329
3330
3331def _CheckAndroidTestJUnitInheritance(input_api, output_api):
3332 """Checks that if new Java test classes have inheritance.
3333 Either the new test class is JUnit3 test or it is a JUnit4 test class
3334 with a base class, either case is undesirable.
3335 """
3336 class_declaration_pattern = input_api.re.compile(r'^public class \w*Test ')
3337
3338 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493339 x, white_list=[r'.*Test\.java$'], black_list=None)
Yoland Yanb92fa522017-08-28 17:37:063340 errors = []
3341 for f in input_api.AffectedFiles(sources):
3342 if not f.OldContents():
3343 class_declaration_start_flag = False
3344 for line_num, line in f.ChangedContents():
3345 if class_declaration_pattern.search(line):
3346 class_declaration_start_flag = True
3347 if class_declaration_start_flag and ' extends ' in line:
3348 errors.append('%s:%d' % (f.LocalPath(), line_num))
3349 if '{' in line:
3350 class_declaration_start_flag = False
3351
3352 results = []
3353 if errors:
3354 results.append(output_api.PresubmitPromptWarning(
3355 'The newly created files include Test classes that inherits from base'
3356 ' class. Please do not use inheritance in JUnit4 tests or add new'
3357 ' JUnit3 tests. Contact [email protected] if you have any'
3358 ' questions.', errors))
3359 return results
3360
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203361
yolandyan45001472016-12-21 21:12:423362def _CheckAndroidTestAnnotationUsage(input_api, output_api):
3363 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
3364 deprecated_annotation_import_pattern = input_api.re.compile(
3365 r'^import android\.test\.suitebuilder\.annotation\..*;',
3366 input_api.re.MULTILINE)
3367 sources = lambda x: input_api.FilterSourceFile(
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493368 x, white_list=[r'.*\.java$'], black_list=None)
yolandyan45001472016-12-21 21:12:423369 errors = []
3370 for f in input_api.AffectedFiles(sources):
3371 for line_num, line in f.ChangedContents():
3372 if deprecated_annotation_import_pattern.search(line):
3373 errors.append("%s:%d" % (f.LocalPath(), line_num))
3374
3375 results = []
3376 if errors:
3377 results.append(output_api.PresubmitError(
3378 'Annotations in android.test.suitebuilder.annotation have been'
3379 ' deprecated since API level 24. Please use android.support.test.filters'
3380 ' from //third_party/android_support_test_runner:runner_java instead.'
3381 ' Contact [email protected] if you have any questions.', errors))
3382 return results
3383
3384
agrieve7b6479d82015-10-07 14:24:223385def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
3386 """Checks if MDPI assets are placed in a correct directory."""
3387 file_filter = lambda f: (f.LocalPath().endswith('.png') and
3388 ('/res/drawable/' in f.LocalPath() or
3389 '/res/drawable-ldrtl/' in f.LocalPath()))
3390 errors = []
3391 for f in input_api.AffectedFiles(include_deletes=False,
3392 file_filter=file_filter):
3393 errors.append(' %s' % f.LocalPath())
3394
3395 results = []
3396 if errors:
3397 results.append(output_api.PresubmitError(
3398 'MDPI assets should be placed in /res/drawable-mdpi/ or '
3399 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
3400 '/res/drawable-ldrtl/.\n'
3401 'Contact [email protected] if you have questions.', errors))
3402 return results
3403
3404
Nate Fischer535972b2017-09-16 01:06:183405def _CheckAndroidWebkitImports(input_api, output_api):
3406 """Checks that code uses org.chromium.base.Callback instead of
Bo Liubfde1c02019-09-24 23:08:353407 android.webview.ValueCallback except in the WebView glue layer
3408 and WebLayer.
Nate Fischer535972b2017-09-16 01:06:183409 """
3410 valuecallback_import_pattern = input_api.re.compile(
3411 r'^import android\.webkit\.ValueCallback;$')
3412
3413 errors = []
3414
3415 sources = lambda affected_file: input_api.FilterSourceFile(
3416 affected_file,
3417 black_list=(_EXCLUDED_PATHS +
3418 _TEST_CODE_EXCLUDED_PATHS +
3419 input_api.DEFAULT_BLACK_LIST +
Bo Liubfde1c02019-09-24 23:08:353420 (r'^android_webview[\\/]glue[\\/].*',
3421 r'^weblayer[\\/].*',)),
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493422 white_list=[r'.*\.java$'])
Nate Fischer535972b2017-09-16 01:06:183423
3424 for f in input_api.AffectedSourceFiles(sources):
3425 for line_num, line in f.ChangedContents():
3426 if valuecallback_import_pattern.search(line):
3427 errors.append("%s:%d" % (f.LocalPath(), line_num))
3428
3429 results = []
3430
3431 if errors:
3432 results.append(output_api.PresubmitError(
3433 'android.webkit.ValueCallback usage is detected outside of the glue'
3434 ' layer. To stay compatible with the support library, android.webkit.*'
3435 ' classes should only be used inside the glue layer and'
3436 ' org.chromium.base.Callback should be used instead.',
3437 errors))
3438
3439 return results
3440
3441
Becky Zhou7c69b50992018-12-10 19:37:573442def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
3443 """Checks Android XML styles """
3444 import sys
3445 original_sys_path = sys.path
3446 try:
3447 sys.path = sys.path + [input_api.os_path.join(
3448 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkxmlstyle')]
3449 import checkxmlstyle
3450 finally:
3451 # Restore sys.path to what it was before.
3452 sys.path = original_sys_path
3453
3454 if is_check_on_upload:
3455 return checkxmlstyle.CheckStyleOnUpload(input_api, output_api)
3456 else:
3457 return checkxmlstyle.CheckStyleOnCommit(input_api, output_api)
3458
3459
agrievef32bcc72016-04-04 14:57:403460class PydepsChecker(object):
3461 def __init__(self, input_api, pydeps_files):
3462 self._file_cache = {}
3463 self._input_api = input_api
3464 self._pydeps_files = pydeps_files
3465
3466 def _LoadFile(self, path):
3467 """Returns the list of paths within a .pydeps file relative to //."""
3468 if path not in self._file_cache:
3469 with open(path) as f:
3470 self._file_cache[path] = f.read()
3471 return self._file_cache[path]
3472
3473 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
3474 """Returns an interable of paths within the .pydep, relativized to //."""
3475 os_path = self._input_api.os_path
3476 pydeps_dir = os_path.dirname(pydeps_path)
3477 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
3478 if not l.startswith('*'))
3479 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
3480
3481 def _CreateFilesToPydepsMap(self):
3482 """Returns a map of local_path -> list_of_pydeps."""
3483 ret = {}
3484 for pydep_local_path in self._pydeps_files:
3485 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
3486 ret.setdefault(path, []).append(pydep_local_path)
3487 return ret
3488
3489 def ComputeAffectedPydeps(self):
3490 """Returns an iterable of .pydeps files that might need regenerating."""
3491 affected_pydeps = set()
3492 file_to_pydeps_map = None
3493 for f in self._input_api.AffectedFiles(include_deletes=True):
3494 local_path = f.LocalPath()
Andrew Grieve892bb3f2019-03-20 17:33:463495 # Changes to DEPS can lead to .pydeps changes if any .py files are in
3496 # subrepositories. We can't figure out which files change, so re-check
3497 # all files.
3498 # Changes to print_python_deps.py affect all .pydeps.
3499 if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'):
agrievef32bcc72016-04-04 14:57:403500 return self._pydeps_files
3501 elif local_path.endswith('.pydeps'):
3502 if local_path in self._pydeps_files:
3503 affected_pydeps.add(local_path)
3504 elif local_path.endswith('.py'):
3505 if file_to_pydeps_map is None:
3506 file_to_pydeps_map = self._CreateFilesToPydepsMap()
3507 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
3508 return affected_pydeps
3509
3510 def DetermineIfStale(self, pydeps_path):
3511 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:413512 import difflib
John Budorick47ca3fe2018-02-10 00:53:103513 import os
3514
agrievef32bcc72016-04-04 14:57:403515 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
3516 cmd = old_pydeps_data[1][1:].strip()
John Budorick47ca3fe2018-02-10 00:53:103517 env = dict(os.environ)
3518 env['PYTHONDONTWRITEBYTECODE'] = '1'
agrievef32bcc72016-04-04 14:57:403519 new_pydeps_data = self._input_api.subprocess.check_output(
John Budorick47ca3fe2018-02-10 00:53:103520 cmd + ' --output ""', shell=True, env=env)
phajdan.jr0d9878552016-11-04 10:49:413521 old_contents = old_pydeps_data[2:]
3522 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:403523 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:413524 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:403525
3526
Tibor Goldschwendt360793f72019-06-25 18:23:493527def _ParseGclientArgs():
3528 args = {}
3529 with open('build/config/gclient_args.gni', 'r') as f:
3530 for line in f:
3531 line = line.strip()
3532 if not line or line.startswith('#'):
3533 continue
3534 attribute, value = line.split('=')
3535 args[attribute.strip()] = value.strip()
3536 return args
3537
3538
agrievef32bcc72016-04-04 14:57:403539def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
3540 """Checks if a .pydeps file needs to be regenerated."""
John Chencde89192018-01-27 21:18:403541 # This check is for Python dependency lists (.pydeps files), and involves
3542 # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
3543 # doesn't work on Windows and Mac, so skip it on other platforms.
agrieve9bc4200b2016-05-04 16:33:283544 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:003545 return []
Tibor Goldschwendt360793f72019-06-25 18:23:493546 is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
agrievef32bcc72016-04-04 14:57:403547 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
3548 results = []
3549 # First, check for new / deleted .pydeps.
3550 for f in input_api.AffectedFiles(include_deletes=True):
Zhiling Huang45cabf32018-03-10 00:50:033551 # Check whether we are running the presubmit check for a file in src.
3552 # f.LocalPath is relative to repo (src, or internal repo).
3553 # os_path.exists is relative to src repo.
3554 # Therefore if os_path.exists is true, it means f.LocalPath is relative
3555 # to src and we can conclude that the pydeps is in src.
3556 if input_api.os_path.exists(f.LocalPath()):
3557 if f.LocalPath().endswith('.pydeps'):
3558 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
3559 results.append(output_api.PresubmitError(
3560 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3561 'remove %s' % f.LocalPath()))
3562 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
3563 results.append(output_api.PresubmitError(
3564 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
3565 'include %s' % f.LocalPath()))
agrievef32bcc72016-04-04 14:57:403566
3567 if results:
3568 return results
3569
3570 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
3571
3572 for pydep_path in checker.ComputeAffectedPydeps():
3573 try:
phajdan.jr0d9878552016-11-04 10:49:413574 result = checker.DetermineIfStale(pydep_path)
3575 if result:
3576 cmd, diff = result
agrievef32bcc72016-04-04 14:57:403577 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:413578 'File is stale: %s\nDiff (apply to fix):\n%s\n'
3579 'To regenerate, run:\n\n %s' %
3580 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:403581 except input_api.subprocess.CalledProcessError as error:
3582 return [output_api.PresubmitError('Error running: %s' % error.cmd,
3583 long_text=error.output)]
3584
3585 return results
3586
3587
glidere61efad2015-02-18 17:39:433588def _CheckSingletonInHeaders(input_api, output_api):
3589 """Checks to make sure no header files have |Singleton<|."""
3590 def FileFilter(affected_file):
3591 # It's ok for base/memory/singleton.h to have |Singleton<|.
3592 black_list = (_EXCLUDED_PATHS +
3593 input_api.DEFAULT_BLACK_LIST +
Egor Paskoce145c42018-09-28 19:31:043594 (r"^base[\\/]memory[\\/]singleton\.h$",
3595 r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]"
Michael Warrese4451492018-03-07 04:42:473596 r"quic_singleton_impl\.h$"))
glidere61efad2015-02-18 17:39:433597 return input_api.FilterSourceFile(affected_file, black_list=black_list)
3598
sergeyu34d21222015-09-16 00:11:443599 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:433600 files = []
3601 for f in input_api.AffectedSourceFiles(FileFilter):
3602 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
3603 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
3604 contents = input_api.ReadFile(f)
3605 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:243606 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:433607 pattern.search(line)):
3608 files.append(f)
3609 break
3610
3611 if files:
yolandyandaabc6d2016-04-18 18:29:393612 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:443613 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:433614 'Please move them to an appropriate source file so that the ' +
3615 'template gets instantiated in a single compilation unit.',
3616 files) ]
3617 return []
3618
3619
[email protected]fd20b902014-05-09 02:14:533620_DEPRECATED_CSS = [
3621 # Values
3622 ( "-webkit-box", "flex" ),
3623 ( "-webkit-inline-box", "inline-flex" ),
3624 ( "-webkit-flex", "flex" ),
3625 ( "-webkit-inline-flex", "inline-flex" ),
3626 ( "-webkit-min-content", "min-content" ),
3627 ( "-webkit-max-content", "max-content" ),
3628
3629 # Properties
3630 ( "-webkit-background-clip", "background-clip" ),
3631 ( "-webkit-background-origin", "background-origin" ),
3632 ( "-webkit-background-size", "background-size" ),
3633 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:443634 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:533635
3636 # Functions
3637 ( "-webkit-gradient", "gradient" ),
3638 ( "-webkit-repeating-gradient", "repeating-gradient" ),
3639 ( "-webkit-linear-gradient", "linear-gradient" ),
3640 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
3641 ( "-webkit-radial-gradient", "radial-gradient" ),
3642 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
3643]
3644
Wei-Yin Chen (陳威尹)f799d442018-07-31 02:20:203645
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493646# TODO: add unit tests
dbeam1ec68ac2016-12-15 05:22:243647def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:533648 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:253649 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:343650 documentation and iOS CSS for dom distiller
3651 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:253652 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:533653 results = []
Wei-Yin Chen (陳威尹)dca729a2018-07-31 21:35:493654 file_inclusion_pattern = [r".+\.css$"]
[email protected]9a48e3f82014-05-22 00:06:253655 black_list = (_EXCLUDED_PATHS +
3656 _TEST_CODE_EXCLUDED_PATHS +
3657 input_api.DEFAULT_BLACK_LIST +
3658 (r"^chrome/common/extensions/docs",
3659 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:343660 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresne6308d7f2016-02-15 09:38:443661 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:253662 r"^native_client_sdk"))
3663 file_filter = lambda f: input_api.FilterSourceFile(
3664 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:533665 for fpath in input_api.AffectedFiles(file_filter=file_filter):
3666 for line_num, line in fpath.ChangedContents():
3667 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:023668 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:533669 results.append(output_api.PresubmitError(
3670 "%s:%d: Use of deprecated CSS %s, use %s instead" %
3671 (fpath.LocalPath(), line_num, deprecated_value, value)))
3672 return results
3673
mohan.reddyf21db962014-10-16 12:26:473674
rlanday6802cf632017-05-30 17:48:363675def _CheckForRelativeIncludes(input_api, output_api):
rlanday6802cf632017-05-30 17:48:363676 bad_files = {}
3677 for f in input_api.AffectedFiles(include_deletes=False):
3678 if (f.LocalPath().startswith('third_party') and
Kent Tamura32dbbcb2018-11-30 12:28:493679 not f.LocalPath().startswith('third_party/blink') and
3680 not f.LocalPath().startswith('third_party\\blink')):
rlanday6802cf632017-05-30 17:48:363681 continue
3682
Daniel Bratell65b033262019-04-23 08:17:063683 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
rlanday6802cf632017-05-30 17:48:363684 continue
3685
Vaclav Brozekd5de76a2018-03-17 07:57:503686 relative_includes = [line for _, line in f.ChangedContents()
rlanday6802cf632017-05-30 17:48:363687 if "#include" in line and "../" in line]
3688 if not relative_includes:
3689 continue
3690 bad_files[f.LocalPath()] = relative_includes
3691
3692 if not bad_files:
3693 return []
3694
3695 error_descriptions = []
3696 for file_path, bad_lines in bad_files.iteritems():
3697 error_description = file_path
3698 for line in bad_lines:
3699 error_description += '\n ' + line
3700 error_descriptions.append(error_description)
3701
3702 results = []
3703 results.append(output_api.PresubmitError(
3704 'You added one or more relative #include paths (including "../").\n'
3705 'These shouldn\'t be used because they can be used to include headers\n'
3706 'from code that\'s not correctly specified as a dependency in the\n'
3707 'relevant BUILD.gn file(s).',
3708 error_descriptions))
3709
3710 return results
3711
Takeshi Yoshinoe387aa32017-08-02 13:16:133712
Daniel Bratell65b033262019-04-23 08:17:063713def _CheckForCcIncludes(input_api, output_api):
3714 """Check that nobody tries to include a cc file. It's a relatively
3715 common error which results in duplicate symbols in object
3716 files. This may not always break the build until someone later gets
3717 very confusing linking errors."""
3718 results = []
3719 for f in input_api.AffectedFiles(include_deletes=False):
3720 # We let third_party code do whatever it wants
3721 if (f.LocalPath().startswith('third_party') and
3722 not f.LocalPath().startswith('third_party/blink') and
3723 not f.LocalPath().startswith('third_party\\blink')):
3724 continue
3725
3726 if not _IsCPlusPlusFile(input_api, f.LocalPath()):
3727 continue
3728
3729 for _, line in f.ChangedContents():
3730 if line.startswith('#include "'):
3731 included_file = line.split('"')[1]
3732 if _IsCPlusPlusFile(input_api, included_file):
3733 # The most common naming for external files with C++ code,
3734 # apart from standard headers, is to call them foo.inc, but
3735 # Chromium sometimes uses foo-inc.cc so allow that as well.
3736 if not included_file.endswith(('.h', '-inc.cc')):
3737 results.append(output_api.PresubmitError(
3738 'Only header files or .inc files should be included in other\n'
3739 'C++ files. Compiling the contents of a cc file more than once\n'
3740 'will cause duplicate information in the build which may later\n'
3741 'result in strange link_errors.\n' +
3742 f.LocalPath() + ':\n ' +
3743 line))
3744
3745 return results
3746
3747
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203748def _CheckWatchlistDefinitionsEntrySyntax(key, value, ast):
3749 if not isinstance(key, ast.Str):
3750 return 'Key at line %d must be a string literal' % key.lineno
3751 if not isinstance(value, ast.Dict):
3752 return 'Value at line %d must be a dict' % value.lineno
3753 if len(value.keys) != 1:
3754 return 'Dict at line %d must have single entry' % value.lineno
3755 if not isinstance(value.keys[0], ast.Str) or value.keys[0].s != 'filepath':
3756 return (
3757 'Entry at line %d must have a string literal \'filepath\' as key' %
3758 value.lineno)
3759 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133760
Takeshi Yoshinoe387aa32017-08-02 13:16:133761
Sergey Ulanov4af16052018-11-08 02:41:463762def _CheckWatchlistsEntrySyntax(key, value, ast, email_regex):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203763 if not isinstance(key, ast.Str):
3764 return 'Key at line %d must be a string literal' % key.lineno
3765 if not isinstance(value, ast.List):
3766 return 'Value at line %d must be a list' % value.lineno
Sergey Ulanov4af16052018-11-08 02:41:463767 for element in value.elts:
3768 if not isinstance(element, ast.Str):
3769 return 'Watchlist elements on line %d is not a string' % key.lineno
3770 if not email_regex.match(element.s):
3771 return ('Watchlist element on line %d doesn\'t look like a valid ' +
3772 'email: %s') % (key.lineno, element.s)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203773 return None
Takeshi Yoshinoe387aa32017-08-02 13:16:133774
Takeshi Yoshinoe387aa32017-08-02 13:16:133775
Sergey Ulanov4af16052018-11-08 02:41:463776def _CheckWATCHLISTSEntries(wd_dict, w_dict, input_api):
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203777 mismatch_template = (
3778 'Mismatch between WATCHLIST_DEFINITIONS entry (%s) and WATCHLISTS '
3779 'entry (%s)')
Takeshi Yoshinoe387aa32017-08-02 13:16:133780
Sergey Ulanov4af16052018-11-08 02:41:463781 email_regex = input_api.re.compile(
3782 r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$")
3783
3784 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203785 i = 0
3786 last_key = ''
3787 while True:
3788 if i >= len(wd_dict.keys):
3789 if i >= len(w_dict.keys):
3790 return None
3791 return mismatch_template % ('missing', 'line %d' % w_dict.keys[i].lineno)
3792 elif i >= len(w_dict.keys):
3793 return (
3794 mismatch_template % ('line %d' % wd_dict.keys[i].lineno, 'missing'))
Takeshi Yoshinoe387aa32017-08-02 13:16:133795
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203796 wd_key = wd_dict.keys[i]
3797 w_key = w_dict.keys[i]
Takeshi Yoshinoe387aa32017-08-02 13:16:133798
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203799 result = _CheckWatchlistDefinitionsEntrySyntax(
3800 wd_key, wd_dict.values[i], ast)
3801 if result is not None:
3802 return 'Bad entry in WATCHLIST_DEFINITIONS dict: %s' % result
Takeshi Yoshinoe387aa32017-08-02 13:16:133803
Sergey Ulanov4af16052018-11-08 02:41:463804 result = _CheckWatchlistsEntrySyntax(
3805 w_key, w_dict.values[i], ast, email_regex)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203806 if result is not None:
3807 return 'Bad entry in WATCHLISTS dict: %s' % result
3808
3809 if wd_key.s != w_key.s:
3810 return mismatch_template % (
3811 '%s at line %d' % (wd_key.s, wd_key.lineno),
3812 '%s at line %d' % (w_key.s, w_key.lineno))
3813
3814 if wd_key.s < last_key:
3815 return (
3816 'WATCHLISTS dict is not sorted lexicographically at line %d and %d' %
3817 (wd_key.lineno, w_key.lineno))
3818 last_key = wd_key.s
3819
3820 i = i + 1
3821
3822
Sergey Ulanov4af16052018-11-08 02:41:463823def _CheckWATCHLISTSSyntax(expression, input_api):
3824 ast = input_api.ast
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203825 if not isinstance(expression, ast.Expression):
3826 return 'WATCHLISTS file must contain a valid expression'
3827 dictionary = expression.body
3828 if not isinstance(dictionary, ast.Dict) or len(dictionary.keys) != 2:
3829 return 'WATCHLISTS file must have single dict with exactly two entries'
3830
3831 first_key = dictionary.keys[0]
3832 first_value = dictionary.values[0]
3833 second_key = dictionary.keys[1]
3834 second_value = dictionary.values[1]
3835
3836 if (not isinstance(first_key, ast.Str) or
3837 first_key.s != 'WATCHLIST_DEFINITIONS' or
3838 not isinstance(first_value, ast.Dict)):
3839 return (
3840 'The first entry of the dict in WATCHLISTS file must be '
3841 'WATCHLIST_DEFINITIONS dict')
3842
3843 if (not isinstance(second_key, ast.Str) or
3844 second_key.s != 'WATCHLISTS' or
3845 not isinstance(second_value, ast.Dict)):
3846 return (
3847 'The second entry of the dict in WATCHLISTS file must be '
3848 'WATCHLISTS dict')
3849
Sergey Ulanov4af16052018-11-08 02:41:463850 return _CheckWATCHLISTSEntries(first_value, second_value, input_api)
Takeshi Yoshinoe387aa32017-08-02 13:16:133851
3852
3853def _CheckWATCHLISTS(input_api, output_api):
3854 for f in input_api.AffectedFiles(include_deletes=False):
3855 if f.LocalPath() == 'WATCHLISTS':
3856 contents = input_api.ReadFile(f, 'r')
3857
3858 try:
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203859 # First, make sure that it can be evaluated.
Takeshi Yoshinoe387aa32017-08-02 13:16:133860 input_api.ast.literal_eval(contents)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203861 # Get an AST tree for it and scan the tree for detailed style checking.
3862 expression = input_api.ast.parse(
3863 contents, filename='WATCHLISTS', mode='eval')
3864 except ValueError as e:
3865 return [output_api.PresubmitError(
3866 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3867 except SyntaxError as e:
3868 return [output_api.PresubmitError(
3869 'Cannot parse WATCHLISTS file', long_text=repr(e))]
3870 except TypeError as e:
3871 return [output_api.PresubmitError(
3872 'Cannot parse WATCHLISTS file', long_text=repr(e))]
Takeshi Yoshinoe387aa32017-08-02 13:16:133873
Sergey Ulanov4af16052018-11-08 02:41:463874 result = _CheckWATCHLISTSSyntax(expression, input_api)
Takeshi Yoshino3a8f9cb52017-08-10 11:32:203875 if result is not None:
3876 return [output_api.PresubmitError(result)]
3877 break
Takeshi Yoshinoe387aa32017-08-02 13:16:133878
3879 return []
3880
3881
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:193882def _CheckNewHeaderWithoutGnChange(input_api, output_api):
3883 """Checks that newly added header files have corresponding GN changes.
3884 Note that this is only a heuristic. To be precise, run script:
3885 build/check_gn_headers.py.
3886 """
3887
3888 def headers(f):
3889 return input_api.FilterSourceFile(
3890 f, white_list=(r'.+%s' % _HEADER_EXTENSIONS, ))
3891
3892 new_headers = []
3893 for f in input_api.AffectedSourceFiles(headers):
3894 if f.Action() != 'A':
3895 continue
3896 new_headers.append(f.LocalPath())
3897
3898 def gn_files(f):
3899 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn', ))
3900
3901 all_gn_changed_contents = ''
3902 for f in input_api.AffectedSourceFiles(gn_files):
3903 for _, line in f.ChangedContents():
3904 all_gn_changed_contents += line
3905
3906 problems = []
3907 for header in new_headers:
3908 basename = input_api.os_path.basename(header)
3909 if basename not in all_gn_changed_contents:
3910 problems.append(header)
3911
3912 if problems:
3913 return [output_api.PresubmitPromptWarning(
3914 'Missing GN changes for new header files', items=sorted(problems),
3915 long_text='Please double check whether newly added header files need '
3916 'corresponding changes in gn or gni files.\nThis checking is only a '
3917 'heuristic. Run build/check_gn_headers.py to be precise.\n'
3918 'Read https://crbug.com/661774 for more info.')]
3919 return []
3920
3921
Michael Giuffridad3bc8672018-10-25 22:48:023922def _CheckCorrectProductNameInMessages(input_api, output_api):
3923 """Check that Chromium-branded strings don't include "Chrome" or vice versa.
3924
3925 This assumes we won't intentionally reference one product from the other
3926 product.
3927 """
3928 all_problems = []
3929 test_cases = [{
3930 "filename_postfix": "google_chrome_strings.grd",
3931 "correct_name": "Chrome",
3932 "incorrect_name": "Chromium",
3933 }, {
3934 "filename_postfix": "chromium_strings.grd",
3935 "correct_name": "Chromium",
3936 "incorrect_name": "Chrome",
3937 }]
3938
3939 for test_case in test_cases:
3940 problems = []
3941 filename_filter = lambda x: x.LocalPath().endswith(
3942 test_case["filename_postfix"])
3943
3944 # Check each new line. Can yield false positives in multiline comments, but
3945 # easier than trying to parse the XML because messages can have nested
3946 # children, and associating message elements with affected lines is hard.
3947 for f in input_api.AffectedSourceFiles(filename_filter):
3948 for line_num, line in f.ChangedContents():
3949 if "<message" in line or "<!--" in line or "-->" in line:
3950 continue
3951 if test_case["incorrect_name"] in line:
3952 problems.append(
3953 "Incorrect product name in %s:%d" % (f.LocalPath(), line_num))
3954
3955 if problems:
3956 message = (
3957 "Strings in %s-branded string files should reference \"%s\", not \"%s\""
3958 % (test_case["correct_name"], test_case["correct_name"],
3959 test_case["incorrect_name"]))
3960 all_problems.append(
3961 output_api.PresubmitPromptWarning(message, items=problems))
3962
3963 return all_problems
3964
3965
Dirk Pranke3c18a382019-03-15 01:07:513966def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api):
3967 # TODO(crbug.com/941824): We need to make sure the entries in
3968 # //buildtools/DEPS are kept in sync with the entries in //DEPS
3969 # so that users of //buildtools in other projects get the same tooling
3970 # Chromium gets. If we ever fix the referenced bug and add 'includedeps'
3971 # support to gclient, we can eliminate the duplication and delete
3972 # this presubmit check.
3973
3974 # Update this regexp if new revisions are added to the files.
3975 rev_regexp = input_api.re.compile(
Dirk Pranke6d095b42019-03-15 23:44:013976 "'((clang_format|libcxx|libcxxabi|libunwind)_revision|gn_version)':")
Dirk Pranke3c18a382019-03-15 01:07:513977
3978 # If a user is changing one revision, they need to change the same
3979 # line in both files. This means that any given change should contain
3980 # exactly the same list of changed lines that match the regexps. The
3981 # replace(' ', '') call allows us to ignore whitespace changes to the
3982 # lines. The 'long_text' parameter to the error will contain the
3983 # list of changed lines in both files, which should make it easy enough
3984 # to spot the error without going overboard in this implementation.
3985 revs_changes = {
3986 'DEPS': {},
3987 'buildtools/DEPS': {},
3988 }
3989 long_text = ''
3990
3991 for f in input_api.AffectedFiles(
3992 file_filter=lambda f: f.LocalPath() in ('DEPS', 'buildtools/DEPS')):
3993 for line_num, line in f.ChangedContents():
3994 if rev_regexp.search(line):
3995 revs_changes[f.LocalPath()][line.replace(' ', '')] = line
3996 long_text += '%s:%d: %s\n' % (f.LocalPath(), line_num, line)
3997
3998 if set(revs_changes['DEPS']) != set(revs_changes['buildtools/DEPS']):
3999 return [output_api.PresubmitError(
4000 'Change buildtools revisions in sync in both //DEPS and '
4001 '//buildtools/DEPS.', long_text=long_text + '\n')]
4002 else:
4003 return []
4004
4005
Daniel Bratell93eb6c62019-04-29 20:13:364006def _CheckForTooLargeFiles(input_api, output_api):
4007 """Avoid large files, especially binary files, in the repository since
4008 git doesn't scale well for those. They will be in everyone's repo
4009 clones forever, forever making Chromium slower to clone and work
4010 with."""
4011
4012 # Uploading files to cloud storage is not trivial so we don't want
4013 # to set the limit too low, but the upper limit for "normal" large
4014 # files seems to be 1-2 MB, with a handful around 5-8 MB, so
4015 # anything over 20 MB is exceptional.
4016 TOO_LARGE_FILE_SIZE_LIMIT = 20 * 1024 * 1024 # 10 MB
4017
4018 too_large_files = []
4019 for f in input_api.AffectedFiles():
4020 # Check both added and modified files (but not deleted files).
4021 if f.Action() in ('A', 'M'):
Dirk Pranked6d45c32019-04-30 22:37:384022 size = input_api.os_path.getsize(f.AbsoluteLocalPath())
Daniel Bratell93eb6c62019-04-29 20:13:364023 if size > TOO_LARGE_FILE_SIZE_LIMIT:
4024 too_large_files.append("%s: %d bytes" % (f.LocalPath(), size))
4025
4026 if too_large_files:
4027 message = (
4028 'Do not commit large files to git since git scales badly for those.\n' +
4029 'Instead put the large files in cloud storage and use DEPS to\n' +
4030 'fetch them.\n' + '\n'.join(too_large_files)
4031 )
4032 return [output_api.PresubmitError(
4033 'Too large files found in commit', long_text=message + '\n')]
4034 else:
4035 return []
4036
Max Morozb47503b2019-08-08 21:03:274037
4038def _CheckFuzzTargets(input_api, output_api):
4039 """Checks specific for fuzz target sources."""
4040 EXPORTED_SYMBOLS = [
4041 'LLVMFuzzerInitialize',
4042 'LLVMFuzzerCustomMutator',
4043 'LLVMFuzzerCustomCrossOver',
4044 'LLVMFuzzerMutate',
4045 ]
4046
4047 REQUIRED_HEADER = '#include "testing/libfuzzer/libfuzzer_exports.h"'
4048
4049 def FilterFile(affected_file):
4050 """Ignore libFuzzer source code."""
4051 white_list = r'.*fuzz.*\.(h|hpp|hcc|cc|cpp|cxx)$'
4052 black_list = r"^third_party[\\/]libFuzzer"
4053
4054 return input_api.FilterSourceFile(
4055 affected_file,
4056 white_list=[white_list],
4057 black_list=[black_list])
4058
4059 files_with_missing_header = []
4060 for f in input_api.AffectedSourceFiles(FilterFile):
4061 contents = input_api.ReadFile(f, 'r')
4062 if REQUIRED_HEADER in contents:
4063 continue
4064
4065 if any(symbol in contents for symbol in EXPORTED_SYMBOLS):
4066 files_with_missing_header.append(f.LocalPath())
4067
4068 if not files_with_missing_header:
4069 return []
4070
4071 long_text = (
4072 'If you define any of the libFuzzer optional functions (%s), it is '
4073 'recommended to add \'%s\' directive. Otherwise, the fuzz target may '
4074 'work incorrectly on Mac (crbug.com/687076).\nNote that '
4075 'LLVMFuzzerInitialize should not be used, unless your fuzz target needs '
4076 'to access command line arguments passed to the fuzzer. Instead, prefer '
4077 'static initialization and shared resources as documented in '
4078 'https://chromium.googlesource.com/chromium/src/+/master/testing/'
4079 'libfuzzer/efficient_fuzzing.md#simplifying-initialization_cleanup.\n' % (
4080 ', '.join(EXPORTED_SYMBOLS), REQUIRED_HEADER)
4081 )
4082
4083 return [output_api.PresubmitPromptWarning(
4084 message="Missing '%s' in:" % REQUIRED_HEADER,
4085 items=files_with_missing_header,
4086 long_text=long_text)]
4087
4088
Mohamed Heikald048240a2019-11-12 16:57:374089def _CheckNewImagesWarning(input_api, output_api):
4090 """
4091 Warns authors who add images into the repo to make sure their images are
4092 optimized before committing.
4093 """
4094 images_added = False
4095 image_paths = []
4096 errors = []
4097 filter_lambda = lambda x: input_api.FilterSourceFile(
4098 x,
4099 black_list=(('(?i).*test', r'.*\/junit\/')
4100 + input_api.DEFAULT_BLACK_LIST),
4101 white_list=[r'.*\/(drawable|mipmap)' ]
4102 )
4103 for f in input_api.AffectedFiles(
4104 include_deletes=False, file_filter=filter_lambda):
4105 local_path = f.LocalPath().lower()
4106 if any(local_path.endswith(extension) for extension in _IMAGE_EXTENSIONS):
4107 images_added = True
4108 image_paths.append(f)
4109 if images_added:
4110 errors.append(output_api.PresubmitPromptWarning(
4111 'It looks like you are trying to commit some images. If these are '
4112 'non-test-only images, please make sure to read and apply the tips in '
4113 'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/speed/'
4114 'binary_size/optimization_advice.md#optimizing-images\nThis check is '
4115 'FYI only and will not block your CL on the CQ.', image_paths))
4116 return errors
4117
4118
dgnaa68d5e2015-06-10 10:08:224119def _AndroidSpecificOnUploadChecks(input_api, output_api):
Becky Zhou7c69b50992018-12-10 19:37:574120 """Groups upload checks that target android code."""
dgnaa68d5e2015-06-10 10:08:224121 results = []
dgnaa68d5e2015-06-10 10:08:224122 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
Jinsong Fan91ebbbd2019-04-16 14:57:174123 results.extend(_CheckAndroidDebuggableBuild(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:224124 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:294125 results.extend(_CheckAndroidToastUsage(input_api, output_api))
Yoland Yanb92fa522017-08-28 17:37:064126 results.extend(_CheckAndroidTestJUnitInheritance(input_api, output_api))
4127 results.extend(_CheckAndroidTestJUnitFrameworkImport(input_api, output_api))
yolandyan45001472016-12-21 21:12:424128 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
Nate Fischer535972b2017-09-16 01:06:184129 results.extend(_CheckAndroidWebkitImports(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574130 results.extend(_CheckAndroidXmlStyle(input_api, output_api, True))
Mohamed Heikald048240a2019-11-12 16:57:374131 results.extend(_CheckNewImagesWarning(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574132 return results
4133
4134def _AndroidSpecificOnCommitChecks(input_api, output_api):
4135 """Groups commit checks that target android code."""
4136 results = []
4137 results.extend(_CheckAndroidXmlStyle(input_api, output_api, False))
dgnaa68d5e2015-06-10 10:08:224138 return results
4139
4140
[email protected]22c9bd72011-03-27 16:47:394141def _CommonChecks(input_api, output_api):
4142 """Checks common to both upload and commit."""
4143 results = []
4144 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:384145 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:544146 excluded_paths=_EXCLUDED_PATHS))
Eric Boren6fd2b932018-01-25 15:05:084147
4148 author = input_api.change.author_email
4149 if author and author not in _KNOWN_ROBOTS:
4150 results.extend(
4151 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
4152
[email protected]55459852011-08-10 15:17:194153 results.extend(
[email protected]760deea2013-12-10 19:33:494154 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
Vaclav Brozek7dbc28c2018-03-27 08:35:234155 results.extend(
4156 _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:544157 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:184158 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
Dominic Battre033531052018-09-24 15:45:344159 results.extend(_CheckNoDISABLETypoInTests(input_api, output_api))
danakj61c1aa22015-10-26 19:55:524160 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:224161 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:444162 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:594163 results.extend(_CheckNoBannedFunctions(input_api, output_api))
Mario Sanchez Prada2472cab2019-09-18 10:58:314164 results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:064165 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:124166 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:184167 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:224168 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:304169 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:494170 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:034171 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:494172 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:444173 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
James Cook6b6597c2019-11-06 22:05:294174 results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
[email protected]d2530012013-01-25 16:39:274175 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
Kent Tamura5a8755d2017-06-29 23:37:074176 results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:544177 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:444178 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:394179 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:554180 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:044181 results.extend(
4182 input_api.canned_checks.CheckChangeHasNoTabs(
4183 input_api,
4184 output_api,
4185 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:404186 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:164187 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]999261d2014-03-03 20:08:084188 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:244189 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
[email protected]99171a92014-06-03 08:44:474190 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:044191 results.extend(_CheckForIPCRules(input_api, output_api))
Stephen Martinis97a394142018-06-07 23:06:054192 results.extend(_CheckForLongPathnames(input_api, output_api))
Daniel Bratell8ba52722018-03-02 16:06:144193 results.extend(_CheckForIncludeGuards(input_api, output_api))
mostynbb639aca52015-01-07 20:31:234194 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:434195 results.extend(_CheckSingletonInHeaders(input_api, output_api))
agrievef32bcc72016-04-04 14:57:404196 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:154197 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:174198 results.extend(_CheckIpcOwners(input_api, output_api))
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:264199 results.extend(_CheckSetNoParent(input_api, output_api))
jbriance9e12f162016-11-25 07:57:504200 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
rlanday6802cf632017-05-30 17:48:364201 results.extend(_CheckForRelativeIncludes(input_api, output_api))
Daniel Bratell65b033262019-04-23 08:17:064202 results.extend(_CheckForCcIncludes(input_api, output_api))
Takeshi Yoshinoe387aa32017-08-02 13:16:134203 results.extend(_CheckWATCHLISTS(input_api, output_api))
Sergiy Byelozyorov366b6482017-11-06 18:20:434204 results.extend(input_api.RunTests(
4205 input_api.canned_checks.CheckVPythonSpec(input_api, output_api)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144206 results.extend(_CheckTranslationScreenshots(input_api, output_api))
Michael Giuffridad3bc8672018-10-25 22:48:024207 results.extend(_CheckCorrectProductNameInMessages(input_api, output_api))
Dirk Pranke3c18a382019-03-15 01:07:514208 results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api))
Daniel Bratell93eb6c62019-04-29 20:13:364209 results.extend(_CheckForTooLargeFiles(input_api, output_api))
Nate Fischerdfd9812e2019-07-18 22:03:004210 results.extend(_CheckPythonDevilInit(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:244211
Vaclav Brozekcdc7defb2018-03-20 09:54:354212 for f in input_api.AffectedFiles():
4213 path, name = input_api.os_path.split(f.LocalPath())
4214 if name == 'PRESUBMIT.py':
4215 full_path = input_api.os_path.join(input_api.PresubmitLocalPath(), path)
Caleb Rouleaua6117be2018-05-11 20:10:004216 test_file = input_api.os_path.join(path, 'PRESUBMIT_test.py')
4217 if f.Action() != 'D' and input_api.os_path.exists(test_file):
Dirk Pranke38557312018-04-18 00:53:074218 # The PRESUBMIT.py file (and the directory containing it) might
4219 # have been affected by being moved or removed, so only try to
4220 # run the tests if they still exist.
4221 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
4222 input_api, output_api, full_path,
4223 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:394224 return results
[email protected]1f7b4172010-01-28 01:17:344225
[email protected]b337cb5b2011-01-23 21:24:054226
[email protected]b8079ae4a2012-12-05 19:56:494227def _CheckPatchFiles(input_api, output_api):
4228 problems = [f.LocalPath() for f in input_api.AffectedFiles()
4229 if f.LocalPath().endswith(('.orig', '.rej'))]
4230 if problems:
4231 return [output_api.PresubmitError(
4232 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:034233 else:
4234 return []
[email protected]b8079ae4a2012-12-05 19:56:494235
4236
Kent Tamura5a8755d2017-06-29 23:37:074237def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api):
Kent Tamura79ef8f82017-07-18 00:00:214238 # Excludes OS_CHROMEOS, which is not defined in build_config.h.
4239 macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|'
4240 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)')
Kent Tamura5a8755d2017-06-29 23:37:074241 include_re = input_api.re.compile(
4242 r'^#include\s+"build/build_config.h"', input_api.re.MULTILINE)
4243 extension_re = input_api.re.compile(r'\.[a-z]+$')
4244 errors = []
4245 for f in input_api.AffectedFiles():
4246 if not f.LocalPath().endswith(('.h', '.c', '.cc', '.cpp', '.m', '.mm')):
4247 continue
4248 found_line_number = None
4249 found_macro = None
4250 for line_num, line in f.ChangedContents():
4251 match = macro_re.search(line)
4252 if match:
4253 found_line_number = line_num
4254 found_macro = match.group(2)
4255 break
4256 if not found_line_number:
4257 continue
4258
4259 found_include = False
4260 for line in f.NewContents():
4261 if include_re.search(line):
4262 found_include = True
4263 break
4264 if found_include:
4265 continue
4266
4267 if not f.LocalPath().endswith('.h'):
4268 primary_header_path = extension_re.sub('.h', f.AbsoluteLocalPath())
4269 try:
4270 content = input_api.ReadFile(primary_header_path, 'r')
4271 if include_re.search(content):
4272 continue
4273 except IOError:
4274 pass
4275 errors.append('%s:%d %s macro is used without including build/'
4276 'build_config.h.'
4277 % (f.LocalPath(), found_line_number, found_macro))
4278 if errors:
4279 return [output_api.PresubmitPromptWarning('\n'.join(errors))]
4280 return []
4281
4282
[email protected]b00342e7f2013-03-26 16:21:544283def _DidYouMeanOSMacro(bad_macro):
4284 try:
4285 return {'A': 'OS_ANDROID',
4286 'B': 'OS_BSD',
4287 'C': 'OS_CHROMEOS',
4288 'F': 'OS_FREEBSD',
4289 'L': 'OS_LINUX',
4290 'M': 'OS_MACOSX',
4291 'N': 'OS_NACL',
4292 'O': 'OS_OPENBSD',
4293 'P': 'OS_POSIX',
4294 'S': 'OS_SOLARIS',
4295 'W': 'OS_WIN'}[bad_macro[3].upper()]
4296 except KeyError:
4297 return ''
4298
4299
4300def _CheckForInvalidOSMacrosInFile(input_api, f):
4301 """Check for sensible looking, totally invalid OS macros."""
4302 preprocessor_statement = input_api.re.compile(r'^\s*#')
4303 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
4304 results = []
4305 for lnum, line in f.ChangedContents():
4306 if preprocessor_statement.search(line):
4307 for match in os_macro.finditer(line):
4308 if not match.group(1) in _VALID_OS_MACROS:
4309 good = _DidYouMeanOSMacro(match.group(1))
4310 did_you_mean = ' (did you mean %s?)' % good if good else ''
4311 results.append(' %s:%d %s%s' % (f.LocalPath(),
4312 lnum,
4313 match.group(1),
4314 did_you_mean))
4315 return results
4316
4317
4318def _CheckForInvalidOSMacros(input_api, output_api):
4319 """Check all affected files for invalid OS macros."""
4320 bad_macros = []
tzik3f295992018-12-04 20:32:234321 for f in input_api.AffectedSourceFiles(None):
ellyjones47654342016-05-06 15:50:474322 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:544323 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
4324
4325 if not bad_macros:
4326 return []
4327
4328 return [output_api.PresubmitError(
4329 'Possibly invalid OS macro[s] found. Please fix your code\n'
4330 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
4331
lliabraa35bab3932014-10-01 12:16:444332
4333def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
4334 """Check all affected files for invalid "if defined" macros."""
4335 ALWAYS_DEFINED_MACROS = (
4336 "TARGET_CPU_PPC",
4337 "TARGET_CPU_PPC64",
4338 "TARGET_CPU_68K",
4339 "TARGET_CPU_X86",
4340 "TARGET_CPU_ARM",
4341 "TARGET_CPU_MIPS",
4342 "TARGET_CPU_SPARC",
4343 "TARGET_CPU_ALPHA",
4344 "TARGET_IPHONE_SIMULATOR",
4345 "TARGET_OS_EMBEDDED",
4346 "TARGET_OS_IPHONE",
4347 "TARGET_OS_MAC",
4348 "TARGET_OS_UNIX",
4349 "TARGET_OS_WIN32",
4350 )
4351 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
4352 results = []
4353 for lnum, line in f.ChangedContents():
4354 for match in ifdef_macro.finditer(line):
4355 if match.group(1) in ALWAYS_DEFINED_MACROS:
4356 always_defined = ' %s is always defined. ' % match.group(1)
4357 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
4358 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
4359 lnum,
4360 always_defined,
4361 did_you_mean))
4362 return results
4363
4364
4365def _CheckForInvalidIfDefinedMacros(input_api, output_api):
4366 """Check all affected files for invalid "if defined" macros."""
4367 bad_macros = []
Mirko Bonadei28112c02019-05-17 20:25:054368 skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/']
lliabraa35bab3932014-10-01 12:16:444369 for f in input_api.AffectedFiles():
Mirko Bonadei28112c02019-05-17 20:25:054370 if any([f.LocalPath().startswith(path) for path in skipped_paths]):
sdefresne4e1eccb32017-05-24 08:45:214371 continue
lliabraa35bab3932014-10-01 12:16:444372 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
4373 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
4374
4375 if not bad_macros:
4376 return []
4377
4378 return [output_api.PresubmitError(
4379 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
4380 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
4381 bad_macros)]
4382
4383
mlamouria82272622014-09-16 18:45:044384def _CheckForIPCRules(input_api, output_api):
4385 """Check for same IPC rules described in
4386 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
4387 """
4388 base_pattern = r'IPC_ENUM_TRAITS\('
4389 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
4390 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
4391
4392 problems = []
4393 for f in input_api.AffectedSourceFiles(None):
4394 local_path = f.LocalPath()
4395 if not local_path.endswith('.h'):
4396 continue
4397 for line_number, line in f.ChangedContents():
4398 if inclusion_pattern.search(line) and not comment_pattern.search(line):
4399 problems.append(
4400 '%s:%d\n %s' % (local_path, line_number, line.strip()))
4401
4402 if problems:
4403 return [output_api.PresubmitPromptWarning(
4404 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
4405 else:
4406 return []
4407
[email protected]b00342e7f2013-03-26 16:21:544408
Stephen Martinis97a394142018-06-07 23:06:054409def _CheckForLongPathnames(input_api, output_api):
4410 """Check to make sure no files being submitted have long paths.
4411 This causes issues on Windows.
4412 """
4413 problems = []
Stephen Martinisc4b246b2019-10-31 23:04:194414 for f in input_api.AffectedTestableFiles():
Stephen Martinis97a394142018-06-07 23:06:054415 local_path = f.LocalPath()
4416 # Windows has a path limit of 260 characters. Limit path length to 200 so
4417 # that we have some extra for the prefix on dev machines and the bots.
4418 if len(local_path) > 200:
4419 problems.append(local_path)
4420
4421 if problems:
4422 return [output_api.PresubmitError(_LONG_PATH_ERROR, problems)]
4423 else:
4424 return []
4425
4426
Daniel Bratell8ba52722018-03-02 16:06:144427def _CheckForIncludeGuards(input_api, output_api):
4428 """Check that header files have proper guards against multiple inclusion.
4429 If a file should not have such guards (and it probably should) then it
4430 should include the string "no-include-guard-because-multiply-included".
4431 """
Daniel Bratell6a75baef62018-06-04 10:04:454432 def is_chromium_header_file(f):
4433 # We only check header files under the control of the Chromium
4434 # project. That is, those outside third_party apart from
4435 # third_party/blink.
Kinuko Yasuda0cdb3da2019-07-31 21:50:324436 # We also exclude *_message_generator.h headers as they use
4437 # include guards in a special, non-typical way.
Daniel Bratell6a75baef62018-06-04 10:04:454438 file_with_path = input_api.os_path.normpath(f.LocalPath())
4439 return (file_with_path.endswith('.h') and
Kinuko Yasuda0cdb3da2019-07-31 21:50:324440 not file_with_path.endswith('_message_generator.h') and
Daniel Bratell6a75baef62018-06-04 10:04:454441 (not file_with_path.startswith('third_party') or
4442 file_with_path.startswith(
4443 input_api.os_path.join('third_party', 'blink'))))
Daniel Bratell8ba52722018-03-02 16:06:144444
4445 def replace_special_with_underscore(string):
Olivier Robinbba137492018-07-30 11:31:344446 return input_api.re.sub(r'[+\\/.-]', '_', string)
Daniel Bratell8ba52722018-03-02 16:06:144447
4448 errors = []
4449
Daniel Bratell6a75baef62018-06-04 10:04:454450 for f in input_api.AffectedSourceFiles(is_chromium_header_file):
Daniel Bratell8ba52722018-03-02 16:06:144451 guard_name = None
4452 guard_line_number = None
4453 seen_guard_end = False
4454
4455 file_with_path = input_api.os_path.normpath(f.LocalPath())
4456 base_file_name = input_api.os_path.splitext(
4457 input_api.os_path.basename(file_with_path))[0]
4458 upper_base_file_name = base_file_name.upper()
4459
4460 expected_guard = replace_special_with_underscore(
4461 file_with_path.upper() + '_')
Daniel Bratell8ba52722018-03-02 16:06:144462
4463 # For "path/elem/file_name.h" we should really only accept
Daniel Bratell39b5b062018-05-16 18:09:574464 # PATH_ELEM_FILE_NAME_H_ per coding style. Unfortunately there
4465 # are too many (1000+) files with slight deviations from the
4466 # coding style. The most important part is that the include guard
4467 # is there, and that it's unique, not the name so this check is
4468 # forgiving for existing files.
Daniel Bratell8ba52722018-03-02 16:06:144469 #
4470 # As code becomes more uniform, this could be made stricter.
4471
4472 guard_name_pattern_list = [
4473 # Anything with the right suffix (maybe with an extra _).
4474 r'\w+_H__?',
4475
Daniel Bratell39b5b062018-05-16 18:09:574476 # To cover include guards with old Blink style.
Daniel Bratell8ba52722018-03-02 16:06:144477 r'\w+_h',
4478
4479 # Anything including the uppercase name of the file.
4480 r'\w*' + input_api.re.escape(replace_special_with_underscore(
4481 upper_base_file_name)) + r'\w*',
4482 ]
4483 guard_name_pattern = '|'.join(guard_name_pattern_list)
4484 guard_pattern = input_api.re.compile(
4485 r'#ifndef\s+(' + guard_name_pattern + ')')
4486
4487 for line_number, line in enumerate(f.NewContents()):
4488 if 'no-include-guard-because-multiply-included' in line:
4489 guard_name = 'DUMMY' # To not trigger check outside the loop.
4490 break
4491
4492 if guard_name is None:
4493 match = guard_pattern.match(line)
4494 if match:
4495 guard_name = match.group(1)
4496 guard_line_number = line_number
4497
Daniel Bratell39b5b062018-05-16 18:09:574498 # We allow existing files to use include guards whose names
Daniel Bratell6a75baef62018-06-04 10:04:454499 # don't match the chromium style guide, but new files should
4500 # get it right.
4501 if not f.OldContents():
Daniel Bratell39b5b062018-05-16 18:09:574502 if guard_name != expected_guard:
Daniel Bratell8ba52722018-03-02 16:06:144503 errors.append(output_api.PresubmitPromptWarning(
4504 'Header using the wrong include guard name %s' % guard_name,
4505 ['%s:%d' % (f.LocalPath(), line_number + 1)],
Istiaque Ahmed9ad6cd22019-10-04 00:26:574506 'Expected: %r\nFound: %r' % (expected_guard, guard_name)))
Daniel Bratell8ba52722018-03-02 16:06:144507 else:
4508 # The line after #ifndef should have a #define of the same name.
4509 if line_number == guard_line_number + 1:
4510 expected_line = '#define %s' % guard_name
4511 if line != expected_line:
4512 errors.append(output_api.PresubmitPromptWarning(
4513 'Missing "%s" for include guard' % expected_line,
4514 ['%s:%d' % (f.LocalPath(), line_number + 1)],
4515 'Expected: %r\nGot: %r' % (expected_line, line)))
4516
4517 if not seen_guard_end and line == '#endif // %s' % guard_name:
4518 seen_guard_end = True
4519 elif seen_guard_end:
4520 if line.strip() != '':
4521 errors.append(output_api.PresubmitPromptWarning(
4522 'Include guard %s not covering the whole file' % (
4523 guard_name), [f.LocalPath()]))
4524 break # Nothing else to check and enough to warn once.
4525
4526 if guard_name is None:
4527 errors.append(output_api.PresubmitPromptWarning(
4528 'Missing include guard %s' % expected_guard,
4529 [f.LocalPath()],
4530 'Missing include guard in %s\n'
4531 'Recommended name: %s\n'
4532 'This check can be disabled by having the string\n'
4533 'no-include-guard-because-multiply-included in the header.' %
4534 (f.LocalPath(), expected_guard)))
4535
4536 return errors
4537
4538
mostynbb639aca52015-01-07 20:31:234539def _CheckForWindowsLineEndings(input_api, output_api):
4540 """Check source code and known ascii text files for Windows style line
4541 endings.
4542 """
earthdok1b5e0ee2015-03-10 15:19:104543 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:234544
4545 file_inclusion_pattern = (
4546 known_text_files,
4547 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
4548 )
4549
mostynbb639aca52015-01-07 20:31:234550 problems = []
Andrew Grieve933d12e2017-10-30 20:22:534551 source_file_filter = lambda f: input_api.FilterSourceFile(
4552 f, white_list=file_inclusion_pattern, black_list=None)
4553 for f in input_api.AffectedSourceFiles(source_file_filter):
Vaclav Brozekd5de76a2018-03-17 07:57:504554 include_file = False
4555 for _, line in f.ChangedContents():
mostynbb639aca52015-01-07 20:31:234556 if line.endswith('\r\n'):
Vaclav Brozekd5de76a2018-03-17 07:57:504557 include_file = True
4558 if include_file:
4559 problems.append(f.LocalPath())
mostynbb639aca52015-01-07 20:31:234560
4561 if problems:
4562 return [output_api.PresubmitPromptWarning('Are you sure that you want '
4563 'these files to contain Windows style line endings?\n' +
4564 '\n'.join(problems))]
4565
4566 return []
4567
4568
Vaclav Brozekd5de76a2018-03-17 07:57:504569def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None):
pastarmovj89f7ee12016-09-20 14:58:134570 """Checks that all source files use SYSLOG properly."""
4571 syslog_files = []
4572 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:564573 for line_number, line in f.ChangedContents():
4574 if 'SYSLOG' in line:
4575 syslog_files.append(f.LocalPath() + ':' + str(line_number))
4576
pastarmovj89f7ee12016-09-20 14:58:134577 if syslog_files:
4578 return [output_api.PresubmitPromptWarning(
4579 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
4580 ' calls.\nFiles to check:\n', items=syslog_files)]
4581 return []
4582
4583
[email protected]1f7b4172010-01-28 01:17:344584def CheckChangeOnUpload(input_api, output_api):
4585 results = []
4586 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:474587 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:284588 results.extend(
jam93a6ee792017-02-08 23:59:224589 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:194590 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:224591 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:134592 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:164593 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
Vaclav Brozekea41ab22018-04-06 13:21:534594 results.extend(_CheckUniquePtr(input_api, output_api))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:194595 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Max Morozb47503b2019-08-08 21:03:274596 results.extend(_CheckFuzzTargets(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544597 return results
[email protected]ca8d1982009-02-19 16:33:124598
4599
[email protected]1bfb8322014-04-23 01:02:414600def GetTryServerMasterForBot(bot):
4601 """Returns the Try Server master for the given bot.
4602
[email protected]0bb112362014-07-26 04:38:324603 It tries to guess the master from the bot name, but may still fail
4604 and return None. There is no longer a default master.
4605 """
4606 # Potentially ambiguous bot names are listed explicitly.
4607 master_map = {
tandriie5587792016-07-14 00:34:504608 'chromium_presubmit': 'master.tryserver.chromium.linux',
4609 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:414610 }
[email protected]0bb112362014-07-26 04:38:324611 master = master_map.get(bot)
4612 if not master:
wnwen4fbaab82016-05-25 12:54:364613 if 'android' in bot:
tandriie5587792016-07-14 00:34:504614 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:364615 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:504616 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:324617 elif 'win' in bot:
tandriie5587792016-07-14 00:34:504618 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:324619 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:504620 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:324621 return master
[email protected]1bfb8322014-04-23 01:02:414622
4623
[email protected]ca8d1982009-02-19 16:33:124624def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:544625 results = []
[email protected]1f7b4172010-01-28 01:17:344626 results.extend(_CommonChecks(input_api, output_api))
Becky Zhou7c69b50992018-12-10 19:37:574627 results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544628 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:274629 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:344630 input_api,
4631 output_api,
[email protected]2fdd1f362013-01-16 03:56:034632 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:274633
jam93a6ee792017-02-08 23:59:224634 results.extend(
4635 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:544636 results.extend(input_api.canned_checks.CheckChangeHasBugField(
4637 input_api, output_api))
Dan Beam39f28cb2019-10-04 01:01:384638 results.extend(input_api.canned_checks.CheckChangeHasNoUnwantedTags(
4639 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:414640 results.extend(input_api.canned_checks.CheckChangeHasDescription(
4641 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:544642 return results
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144643
4644
4645def _CheckTranslationScreenshots(input_api, output_api):
Mustafa Emre Acerad8fb082019-11-19 04:24:214646 PART_FILE_TAG = "part"
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144647 import os
4648 import sys
4649 from io import StringIO
4650
4651 try:
4652 old_sys_path = sys.path
4653 sys.path = sys.path + [input_api.os_path.join(
Mustafa Emre Acerad8fb082019-11-19 04:24:214654 input_api.PresubmitLocalPath(), 'tools', 'grit')]
4655 import grit.grd_reader
4656 import grit.node.message
4657 import grit.util
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144658 finally:
4659 sys.path = old_sys_path
4660
Mustafa Emre Acerad8fb082019-11-19 04:24:214661 def _GetGrdMessages(grd_path_or_string, dir_path='.'):
4662 """Load the grd file and return a dict of message ids to messages.
4663
4664 Ignores any nested grdp files pointed by <part> tag.
4665 """
4666 doc = grit.grd_reader.Parse(grd_path_or_string, dir_path,
4667 stop_after=None, first_ids_file=None,
4668 debug=False, defines={'_chromium': 1},
4669 tags_to_ignore=set([PART_FILE_TAG]))
4670 return {
4671 msg.attrs['name']:msg for msg in doc.GetChildrenOfType(
4672 grit.node.message.MessageNode)
4673 }
4674
4675 def _GetGrdpMessagesFromString(grdp_string):
4676 """Parses the contents of a grdp file given in grdp_string.
4677
4678 grd_reader can't parse grdp files directly. Instead, this creates a
4679 temporary directory with a grd file pointing to the grdp file, and loads the
4680 grd from there. Any nested grdp files (pointed by <part> tag) are ignored.
4681 """
4682 WRAPPER = """<?xml version="1.0" encoding="utf-8"?>
4683 <grit latest_public_release="1" current_release="1">
4684 <release seq="1">
4685 <messages>
4686 <part file="sub.grdp" />
4687 </messages>
4688 </release>
4689 </grit>
4690 """
4691 with grit.util.TempDir({'main.grd': WRAPPER,
4692 'sub.grdp': grdp_string}) as temp_dir:
4693 return _GetGrdMessages(temp_dir.GetPath('main.grd'), temp_dir.GetPath())
4694
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144695 new_or_added_paths = set(f.LocalPath()
4696 for f in input_api.AffectedFiles()
4697 if (f.Action() == 'A' or f.Action() == 'M'))
4698 removed_paths = set(f.LocalPath()
4699 for f in input_api.AffectedFiles(include_deletes=True)
4700 if f.Action() == 'D')
4701
4702 affected_grds = [f for f in input_api.AffectedFiles()
4703 if (f.LocalPath().endswith('.grd') or
4704 f.LocalPath().endswith('.grdp'))]
4705 affected_png_paths = [f.AbsoluteLocalPath()
4706 for f in input_api.AffectedFiles()
4707 if (f.LocalPath().endswith('.png'))]
4708
4709 # Check for screenshots. Developers can upload screenshots using
4710 # tools/translation/upload_screenshots.py which finds and uploads
4711 # images associated with .grd files (e.g. test_grd/IDS_STRING.png for the
4712 # message named IDS_STRING in test.grd) and produces a .sha1 file (e.g.
4713 # test_grd/IDS_STRING.png.sha1) for each png when the upload is successful.
4714 #
4715 # The logic here is as follows:
4716 #
4717 # - If the CL has a .png file under the screenshots directory for a grd
4718 # file, warn the developer. Actual images should never be checked into the
4719 # Chrome repo.
4720 #
4721 # - If the CL contains modified or new messages in grd files and doesn't
4722 # contain the corresponding .sha1 files, warn the developer to add images
4723 # and upload them via tools/translation/upload_screenshots.py.
4724 #
4725 # - If the CL contains modified or new messages in grd files and the
4726 # corresponding .sha1 files, everything looks good.
4727 #
4728 # - If the CL contains removed messages in grd files but the corresponding
4729 # .sha1 files aren't removed, warn the developer to remove them.
4730 unnecessary_screenshots = []
4731 missing_sha1 = []
4732 unnecessary_sha1_files = []
4733
4734
4735 def _CheckScreenshotAdded(screenshots_dir, message_id):
4736 sha1_path = input_api.os_path.join(
4737 screenshots_dir, message_id + '.png.sha1')
4738 if sha1_path not in new_or_added_paths:
4739 missing_sha1.append(sha1_path)
4740
4741
4742 def _CheckScreenshotRemoved(screenshots_dir, message_id):
4743 sha1_path = input_api.os_path.join(
4744 screenshots_dir, message_id + '.png.sha1')
meacere7be7532019-10-02 17:41:034745 if input_api.os_path.exists(sha1_path) and sha1_path not in removed_paths:
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144746 unnecessary_sha1_files.append(sha1_path)
4747
4748
4749 for f in affected_grds:
4750 file_path = f.LocalPath()
4751 old_id_to_msg_map = {}
4752 new_id_to_msg_map = {}
4753 if file_path.endswith('.grdp'):
4754 if f.OldContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214755 old_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394756 unicode('\n'.join(f.OldContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144757 if f.NewContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214758 new_id_to_msg_map = _GetGrdpMessagesFromString(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394759 unicode('\n'.join(f.NewContents())))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144760 else:
4761 if f.OldContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214762 old_id_to_msg_map = _GetGrdMessages(
4763 StringIO(unicode('\n'.join(f.OldContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144764 if f.NewContents():
Mustafa Emre Acerad8fb082019-11-19 04:24:214765 new_id_to_msg_map = _GetGrdMessages(
4766 StringIO(unicode('\n'.join(f.NewContents()))))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144767
4768 # Compute added, removed and modified message IDs.
4769 old_ids = set(old_id_to_msg_map)
4770 new_ids = set(new_id_to_msg_map)
4771 added_ids = new_ids - old_ids
4772 removed_ids = old_ids - new_ids
4773 modified_ids = set([])
4774 for key in old_ids.intersection(new_ids):
4775 if (old_id_to_msg_map[key].FormatXml()
4776 != new_id_to_msg_map[key].FormatXml()):
4777 modified_ids.add(key)
4778
4779 grd_name, ext = input_api.os_path.splitext(
4780 input_api.os_path.basename(file_path))
4781 screenshots_dir = input_api.os_path.join(
4782 input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_'))
4783
4784 # Check the screenshot directory for .png files. Warn if there is any.
4785 for png_path in affected_png_paths:
4786 if png_path.startswith(screenshots_dir):
4787 unnecessary_screenshots.append(png_path)
4788
4789 for added_id in added_ids:
4790 _CheckScreenshotAdded(screenshots_dir, added_id)
4791
4792 for modified_id in modified_ids:
4793 _CheckScreenshotAdded(screenshots_dir, modified_id)
4794
4795 for removed_id in removed_ids:
4796 _CheckScreenshotRemoved(screenshots_dir, removed_id)
4797
4798 results = []
4799 if unnecessary_screenshots:
4800 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394801 'Do not include actual screenshots in the changelist. Run '
4802 'tools/translate/upload_screenshots.py to upload them instead:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144803 sorted(unnecessary_screenshots)))
4804
4805 if missing_sha1:
4806 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394807 'You are adding or modifying UI strings.\n'
4808 'To ensure the best translations, take screenshots of the relevant UI '
4809 '(https://g.co/chrome/translation) and add these files to your '
4810 'changelist:', sorted(missing_sha1)))
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144811
4812 if unnecessary_sha1_files:
4813 results.append(output_api.PresubmitNotifyResult(
Mustafa Emre Acerc8a012d2018-07-31 00:00:394814 'You removed strings associated with these files. Remove:',
Mustafa Emre Acer29bf6ac92018-07-30 21:42:144815 sorted(unnecessary_sha1_files)))
4816
4817 return results